2009-07-26 6 views
1

J'ai décidé de faire un wrapper pour strncpy car mon code source me demande de faire beaucoup de copies de chaînes. Et je veux m'assurer que la chaîne est terminée si la source est égale ou supérieure à la destination.Création d'un wrapper pour strncpy à insérer Terminer null

Ce code sera utilisé en production, donc je veux juste voir s'il y a des dangers potentiels en utilisant cette enveloppe.

Je n'ai jamais fait d'emballage auparavant, donc j'essaie de le rendre parfait.

Un grand merci pour tous les conseils,

/* Null terminate a string after coping */ 
char* strncpy_wrapper(char *dest, const char* source, 
         const size_t dest_size, const size_t source_size) 
{ 
    strncpy(dest, source, dest_size); 
    /* 
    * Compare the different length, if source is greater 
    * or equal to the destination terminate with a null. 
    */ 
    if(source_size >= dest_size) 
    { 
     dest[dest_size - 1] = '\0'; 
    } 

    return dest; 
} 

==== ==== mis à jour sous la direction

/* Null terminate a string after coping */ 
char* strncpy_wrapper(char *dest, const char* source, 
         const size_t dest_size) 
{ 
    strncpy(dest, source, dest_size); 
    /* 
    * If the destination is greater than zero terminate with a null. 
    */ 
    if(dest_size > 0) 
    { 
     dest[dest_size - 1] = '\0'; 
    } 
    else 
    { 
     dest[0] = '\0'; /* Return empty string if the destination is zero length */ 
    } 

    return dest; 
} 

Répondre

2

Vérifiez dest_size avant d'accéder au tableau ou vous avoir des ennuis:

if (dest_size > 0) { 
    dest[dest_size - 1] = '\0'; 
} 

En fait, maintenant que je pense, il est probablement préférable de mourir juste:

if (dest_size == 0) { 
    fputs(stderr, "strncpy(x,y,0)"); 
    exit(1); 
} 

Sinon, vous aurez le même problème qu'avec l'original strncpy(), que dest ne peut être résilié si dest_size est 0.

+0

Je viens d'éditer ma question avec le code source mis à jour. J'ai mis un sinon. Si la dest est supérieure à 0. Terminez toujours le dernier élément. Sinon, insérez une valeur nulle dans le premier élément [0] et renvoyez une chaîne de destination vide. Qu'est-ce que ça sonne? – ant2009

+0

Vous ne pouvez pas stocker un '\ 0' dans * dest * si * dest * a une taille nulle. Vous n'êtes pas autorisé à le faire, car vous ne pouvez accéder qu'aux caractères zéro, mais l'enregistrement d'un \ 0 signifie que vous accédez à un caractère. Je ne pense pas que ce soit un problème de mourir, c'est comme une division par zéro erreurs. Cela n'a aucun sens d'appeler votre fonction avec * dest_size == 0 *. C'est une bonne idée de * échouer tôt *, alors vous savez au moins où vous avez foiré (dans l'appel à strncpy()). Imaginez que l'opération de division échoue silencieusement et vous donne des déchets aléatoires. très difficile à déboguer. – Inshallah

3

Vous n'avez pas besoin de vérifier que la source est supérieure à destination juste toujours faire le dernier caractère de la destination a '\ 0'.

1

Si vous ne disposez pas de contraintes sur l'attribution du tampon, strndup pourrait être plus approprié.

Il alloue et copie au maximum len caractères, et se termine toujours par NULL.

1

si dest_size est le nombre de caractères à copier et source_size est le nombre de caractères dans la chaîne source.
vous devriez essayer ceci:


size_t numchars = dest_size > source_size ? source_size : dest_size; 
strncpy(dest,source,numchars) ; 
dest[numchars] = 0 ; 
+1

* strncpy() * ne fermera pas ** 0 ** * dest * par lui-même. Le caractère 0 proviendra toujours de * source *. Cela signifie que votre exemple ne fonctionnera pas comme l'OP l'a prévu. – Inshallah

+0

@ dessus édité .. comme indiqué – sud03r

2

Vous devriez enquêter sur les fonctions BSD semi-standard strlcpy() et strlcat().

Vous devez vérifier si les fonctions ISO TR24731 telles que strncpy_s() sont appropriées et disponibles là où vous en avez besoin.