2009-08-01 12 views
3

Merci de regarder, s'il vous plaît ignorer - toutes sortes de manigances se produisent et j'essaie de déboguer plus.Realloc problème

=====================================

Quelqu'un peut-il expliquer ce comportement de realloc?

Sortie:

before realloc start: testing%20encryp 
before realloc app: '   ' 
realloc size: 27 
after realloc: testing%20e 
strlen(newstr): 11 
newstr: testing%20e 

code:

char * strAppend(char * start, char * app) 
{ 
    int i=strlen(start); 
    int j=0; 
    printf("before realloc start: %s\n", start); 
    printf("before realloc app: '%s'\n", app); 
    printf("realloc size: %i\n", i+strlen(app)+1); 
    char * newstr = realloc(start, sizeof(char) * (i + strlen(app) + 1)); 
    printf("after realloc: %s\n", newstr); 
    while(app[j] != '\0') 
    newstr[i++] = app[j++]; 
    printf("strlen(newstr): %i\n", strlen(newstr)); 
    printf("newstr: %s\n", newstr); 
    return newstr; } 

C'est la suppression de "ncryp" du début après la realloc; mais ce n'est pas censé se produire ....

Edit: Plus Code, Plus sortie

char * urlEncode(char * c) 
{ 
#ifdef EBUG 
    printf("urlEncode: Encoding '%s'\n", c); 
#endif 
    int len = strlen(c)+1; 
    char * ret = malloc(sizeof(char) * len); 
    memset(ret, 0, len); 
    int z=0; 
    char * escapee = malloc(sizeof(char) * 4); 
    escapee[0] = '%'; escapee[3] = '\0'; 
    for(int i=0;i<strlen(c);i++) 
    { 
     printf("z = %i len = %i ret = %s\n", z, len, ret); 
     if(z >= len) 
     { 
      ret = strAppend(ret, "   "); 
      len += strlen("   "); 
     } 
     printf("z = %i len = %i ret = %s\n", z, len, ret); 
     if ((48 <= c[i] && c[i] <= 57) ||//0-9 
      (65 <= c[i] && c[i] <= 90) ||//abc...xyz 
      (97 <= c[i] && c[i] <= 122) || //ABC...XYZ 
      (c[i]=='~' || c[i]=='!' || c[i]=='*' || c[i]=='(' || c[i]==')' || c[i]=='\'') 
      ) 
     { 
      ret[z++] = c[i]; 
     } 
     else 
     { 
      char2hex(c[i], escapee); 
      ret = strAppend(ret, escapee); 
      z += 3; 
     } 
    } 
    ret[z] = '\0'; 
    free(escapee); 
#ifdef EBUG 
    printf("urlEncode: Encoded string to '%s'\n", c); 
#endif 
    return ret; 
} 




urlEncode: Encoding 'testing encrypt' 
z = 0 len = 16 ret = 
z = 0 len = 16 ret = 
z = 1 len = 16 ret = t 
z = 1 len = 16 ret = t 
z = 2 len = 16 ret = te 
z = 2 len = 16 ret = te 
z = 3 len = 16 ret = tes 
z = 3 len = 16 ret = tes 
z = 4 len = 16 ret = test 
z = 4 len = 16 ret = test 
z = 5 len = 16 ret = testi 
z = 5 len = 16 ret = testi 
z = 6 len = 16 ret = testin 
z = 6 len = 16 ret = testin 
z = 7 len = 16 ret = testing 
z = 7 len = 16 ret = testing 
before realloc start: testing 
before realloc app: '%20' 
realloc size: 11 
after realloc: testing 
strlen(newstr): 10 
newstr: testing%20 
z = 10 len = 16 ret = testing%20 
z = 10 len = 16 ret = testing%20 
z = 11 len = 16 ret = testing%20e 
z = 11 len = 16 ret = testing%20e 
z = 12 len = 16 ret = testing%20en 
z = 12 len = 16 ret = testing%20en 
z = 13 len = 16 ret = testing%20enc 
z = 13 len = 16 ret = testing%20enc 
z = 14 len = 16 ret = testing%20encr 
z = 14 len = 16 ret = testing%20encr 
z = 15 len = 16 ret = testing%20encry 
z = 15 len = 16 ret = testing%20encry 
z = 16 len = 16 ret = testing%20encryp 
before realloc start: testing%20encryp 
before realloc app: '   ' 
realloc size: 27 
after realloc: testing%20encryp 
strlen(newstr): 26 
newstr: testing%20encryp 
z = 16 len = 26 ret = testing%20encryp 

Dernière édition:

Je ne sais pas ce qui se passe au moment . Différentes exécutions du programme avec et sans indicateurs de débogage produisent une sortie différente. Je retourne à la planche à dessin et je cherche des erreurs de mémoire en utilisant valgrind.

+1

Pouvez-vous poster le code appelant. En particulier, d'où vient le départ? –

+0

IIRC sizeof (char) est toujours 1. –

+1

J'espère que vous savez qu'en faisant 'realloc (start, ...)', * start * pourrait devenir un pointeur invalide. –

Répondre

1

Le premier paramètre à realloc doit être un pointeur renvoyé précédemment par malloc, calloc ou realloc et non par la suite d free.

Si ce n'est pas le cas, tout peut arriver, y compris ce que vous avez vu.

D'où vient start?

Modifier: postez votre modification, vous ne semblez pas avoir de problème de realloc!

+2

Pas tout à fait. Le premier argument pourrait bien être 'NULL'. – Jens

1

Je pense que ce que vous essayez de faire est de concaténer deux chaînes commencent application &, si tel est le cas, il vaut mieux utiliser la fonction strncat

#include <cstring> 
char *strncat(char *str1, const char *str2, size_t count); 
+0

Droit, mais je veux gérer la gestion de la mémoire et de développer str1 dans la fonction, plutôt qu'avant d'appeler strncat –

+0

Je ne comprends pas ce que vous voulez dire, strncat va développer la chaîne pour vous – bashmohandes

+1

strncat ne pousse pas la région de mémoire sous-jacente . Il ajoute simplement la deuxième chaîne à la première et s'appuie sur l'appelant lui ayant donné les limites appropriées pour empêcher tout dépassement de mémoire tampon. –

1

Comme il semble que votre problème realloc d'origine n'a pas été reproductible , Je vais oser poster un code légèrement refactorisé qui fait ce que vous cherchez. Il fait deux passes sur la chaîne, mais à mon avis, il devrait avoir une performance plus prévisible en termes de nombre d'appels d'allocation de mémoire effectués - une seule fois. C'est aussi un peu plus court que le tien.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int is_printable(char c) { 
return (48 <= c && c <= 57) ||//0-9 
     (65 <= c && c <= 90) ||//abc...xyz 
     (97 <= c && c <= 122) || //ABC...XYZ 
     c == '~' || c =='!' || c== '*' || 
     c == '(' || c== ')' || c== '\''; 
} 

char *urlEncode(char *s) { 
    char *ret, *c, *ct; 
    int i, len; 
    printf("urlEncode: Encoding '%s'\n", s); 
    /* First pass - figure out how long the target string should be */ 
    len = 0; 
    for(c=s; *c; c++) { 
    if(is_printable(*c)) len++; else len += 3; 
    } 
    /* Don't forget we need to store terminating zero too */ 
    len++; 
    printf("Current len: %d, target len: %d\n", strlen(s)+1, len); 
    ct = ret = malloc(len); 
    /* Second pass - copy/encode */ 
    for(c=s; *c; c++) { 
    if(is_printable(*c)) { 
     *ct++ = *c; 
    } else { 
     snprintf(ct, 4, "%%%02x", *c); 
     ct += 3; 
    } 
    } 
    *ct = 0; /* null-terminate the string */ 
    printf("Encoded string: %s\n", ret); 
    return ret; 
} 

int main(int argc, char *argv[]) 
{ 
    urlEncode("testing encrypt"); 
    exit(1); 
} 
+0

Merci, c'est mieux. Mais il y a un petit bug: il semble inverser les valeurs encodées: "Encoded string: testing% 02encrypt" au lieu de% 20 –

+0

Merci, en effet. La chaîne de format était erronée - il ne retournait pas les parties, il était toujours l'impression% 02 :) 'l'homme snprintf' est mon ami ... –

+0

merci, fonctionne bien – Ulterior

0
char * strAppend(char * start, char * app) 
{ 
    int i=strlen(start); 
    int j=0; 
    printf("before realloc start: %s\n", start); 
    printf("before realloc app: '%s'\n", app); 
    printf("realloc size: %i\n", i+strlen(app)+1); 
    char * newstr =(void*) realloc(start, sizeof(char) * (i + strlen(app) + 1)); 


    memset(newstr,'z',sizeof(char) * (i + strlen(app) + 1)); 
    printf("addres %x\n",newstr); 

    printf("after realloc: %s\n", newstr); 
    while(app[j] != '\0') 
    newstr[i++] = app[j++]; 

    //missing null terminating character 
    newstr[i]=0; 

    printf("strlen(newstr): %i\n", strlen(newstr)); 
    printf("newstr: %s\n", newstr); 
    return newstr; 
    } 

et dans mon système l'adresse du newstr de chaîne allouée est égale à commencer, peu importe quelle est la taille allouée de « départ », aparently le système réaffecte la même position de la mémoire lorsqu'elle grandit