2009-04-08 7 views
0

J'essaye d'écrire une fonction qui décale tous les éléments d'un tableau de chaînes de un.Décaler toutes les chaînes dans le tableau (problème avec realloc)

void shift_frags(char **frags, int frag_len, int cur) 
{ 
    int i; 
    for(i = cur; i < frag_len-1; i++) 
    { 
     if(strlen(frags[i+1]) > strlen(frags[i])) 
      frags[i] = realloc(frags[i], strlen(frags[i+1])*sizeof(char)); 
     strcpy(frags[i], frags[i+1]); 
    } 

    free(frags[frag_len-1]); 
} 

Cela me donne l'erreur: « realloc(): taille suivante invalide: ... » Chaque tableau est alloué dynamiquement à la taille d'une chaîne lue à partir d'un fichier. Ne devrais-je pas être en mesure d'allouer dynamiquement de nouvelles tailles de tableau puisque mon paramètre frags est un tableau de pointeurs?

Merci

+0

Le calcul de sizeof (char) consiste simplement à ajouter de l'obfuscation au code. Il est toujours égal à 1. – unwind

Répondre

3

Depuis que vous dites le tableau est juste un tableau de pointeurs, vous n'avez pas besoin d'effectuer des réaffectations. Vous avez juste besoin de copier les pointeurs eux-mêmes. Un simple appel à memmove ou quelque chose de similaire dans la partie du tableau est tout ce qui est nécessaire.

Quelque chose d'approximatif.

void shift_frags(char **frags, int frag_len, int cur) 
{ 
    free(frags[frag_len]); 
    memmove(frags+cur+1, frags+cur, (frag_len-cur) * sizeof(char*)); 
} 
+0

ne pas oublier de multiplier frag_len par sizeof (char *) – Alnitak

+0

Vous plaisantez? char est toujours la taille 1 octet –

+0

Ou mieux encore, par sizeof * frags pour éviter la répétition inutile du type. – unwind

2

Il n'y a pas besoin de free()/realloc() du tout.

Votre char **frags est un pointeur vers une liste de pointeurs de sorte que vous pouvez simplement mélanger les valeurs de pointeur sans créer de nouvelles chaînes.

Assurez-vous que vous commencez à l'extrémité de la liste, et compter à rebours, ou utilisez memmove():

void shift_frags(char **frags, int frag_len, int cur) 
{ 
    int i; 

    free(frags[frag_len]); /* because otherwise this is left dangling */ 

    for(i = frag_len; i > cur; i--) 
    { 
     frags[i] = frags[i - 1]; 
    } 
} 

ou:

void shift_frags(char **frags, int frag_len, int cur) 
{ 
    int n = frag_len - cur; 
    frags += cur; 
    free(frags[n]); 
    memmove(frags + 1, frags, n * sizeof(*frags)); /* nb: memmove(dst, src, n) */ 
} 

NB: il y a un possible hors sous- une erreur ici, cela dépend de la sémantique de votre valeur frag_len, et si vous savez que le bloc de mémoire frag est déjà assez grand pour contenir un autre pointeur.

1

Votre realloc échoue probablement parce que vous n'êtes pas réserver un octet pour le NUL arrière (« \ 0 ») de caractère dans les chaînes - ajouter un +1 à votre taille realloc:

if(strlen(frags[i+1]) > strlen(frags[i])) 
     frags[i] = realloc(frags[i], (strlen(frags[i+1]) + 1)*sizeof(char)); 
    strcpy(frags[i], frags[i+1]); 

corrigera ce bug. L'erreur spécifique que vous obtenez est probable parce qu'une de vos chaînes est de longueur 0, et que realloc (foo, 0) vous donne simplement cette erreur sur votre système, ou parce que vous écrivez le '\ 0' final dans la mémoire non allouée et écraser quelque chose d'autre important, provoquant la corruption.

Simplement réorganiser les pointeurs (frags [i] = frags [i + 1] ou utiliser memmove()) est plus facile, plus rapide et vous évite de gaspiller de la mémoire.

Questions connexes