2012-12-01 1 views
0

Je suis dans une situation où je dois faire une concaténation de C-String, alors j'ai décidé de prendre sur moi-même pour apprendre (ceci est juste un projet personnel, donc j'ai tous les temps dans le monde, vraiment).C Fonction de concaténation de chaîne de caractères

Jusqu'à présent, je suis venu avec ces deux fonctions (explication donnée ci-dessous):

static inline // make inline to leave out the stack manipulation 
size_t StrLength(const char* string) 
{ 
    return strnlen(string, strlen(string)); 
} 

static void concatstr(char** dest, const char** src) 
{ 
    const size_t destlen = StrLength(*dest); 
    const size_t srclen = StrLength(*src); 

    const size_t total_len = destlen + srclen; 

    const size_t totalLenNull = total_len + 1; 

    char* tmp = (char*)malloc(sizeof(char) * totalLenNull); //<-- Because of this... 

    size_t counter = 0; 

    for(size_t iDest = 0; iDest < destlen; ++iDest) 
     tmp[ counter++ ] = *dest[ iDest ]; 

    for (size_t iSrc = 0; iSrc < srclen; ++iSrc) 
     tmp[ counter++ ] = *src[ iSrc ]; 

    *dest = (char*) realloc(*dest, totalLenNull); 

    strncpy(*dest, tmp, total_len); 

    free(tmp); 

    tmp = NULL; 
} 

L'idée derrière la fonction StrLength en ligne est que, si je comprends bien aligné, il est censé fonctionner comme un Une macro plus sûre en C++, donc c'est moins sujet aux bugs (je pense). Je l'ai fait en ligne puisque c'est juste une ligne de code, et une manipulation de pile pour ce genre de processus semble un peu trop. Si j'ai tort, corrigez-moi s'il vous plaît.

Maintenant, sur la fonction concatstr():

Le problème ici est que dès que je reçois à la deuxième boucle, le programme se bloque sur la 2e itération en raison d'une mémoire vive violation. Pourquoi cela arrive je ne suis pas sûr.

Le code d'appel se présente comme suit:

const size_t len = StrLength(msg) + mPrefix.length() + StrLength("\n\n"); 

char* out = (char*)malloc(sizeof(char) * (len + 1)); 

out[0] = '\0'; 

const char* tmp_pass = mPrefix.c_str(); 

concatstr(&out, &tmp_pass); 
concatstr(&out, &msg); 

La seule raison pour laquelle je mets une étiquette visuelle-C++ est que même si je fais cela comme on le ferait en c droite, je suis en utilisant VC++ en tant que compilateur.

Est-ce que quelqu'un a une idée de ce que le problème est ici?

+1

Vous n'avez pas besoin de 'StrLength()'; surtout après avoir lu le code de cette fonction; utilisez 'strlen()' directement. S'il vous plaît voir http://en.cppreference.com/w/cpp/language/operator_precedence. '[]' a la priorité sur '*' et vous l'utilisez à 2 endroits. – foxx1337

Répondre

2

Vous avez les préséances mal,

tmp[ counter++ ] = *dest[ iDest ]; 

est (implicitement) parethesised

tmp[ counter++ ] = *(dest[ iDest ]); 

mais vous avez besoin

tmp[ counter++ ] = (*dest)[ iDest ]; 

avec des parenthèses explicites.

Sans les parenthèses, le (présumé) char* à un décalage de iDest * sizeof(char*) octets après *dest est déréférencé, il n'y a probablement pas un char* valide que vous êtes autorisé à déréférencer. Vous voulez accéder à l'octet à un décalage de iDest octets après ce que *dest indique.

A la fin,

strncpy(*dest, tmp, total_len); 

n'a pas 0-les chaînes concaténées se terminent. Vous avez besoin de totalLenNull là.

En plus:

return strnlen(string, strlen(string)); 

est plutôt circonspect. Vous devez d'abord parcourir string pour trouver l'octet de fin, en comptant char avant cela. Ensuite, vous vérifiez s'il existe un octet de fin parmi les premiers strlen(string) octets de string. À moins que string soit modifié entre ces deux appels (et que vous soyez probablement arrosé), le second retournera exactement le même que le premier appel.

Questions connexes