2010-11-30 6 views
0

Je rencontre des problèmes avec un tableau de chaînes qui semblent envahir un espace de mémoire réservé. Le code est trop grand pour poster ici, donc je posterai la partie importante ci-dessous:Erreur de segmentation avec un tableau de chaînes

int main (){ 

int i = 0, j = 0, k = 0, count = 0, numLinhas = 0, l = 0; 
char string[100][100]; 
char line [17]; 
char str[4]; 
char str1[5]; 
char str2[4]; 
char str3[4]; 

FILE *p; 
p = fopen("text.txt", "r"); 
while(fgets(line, sizeof line, p)!=NULL){ 
    printf("%s", line); 
    strncpy(string[i], line, 17); 
    i++; 
    numLinhas++; 
    } 
    fclose(p); 
    char *temp[numLinhas]; 

Après cela, il va dans une boucle qui stocke dans string [i] le sens de la déclaration contenue dans le fichier. Le début des exemples for et three est indiqué ci-dessous:

for (i = 0; i<numLinhas; i++){ 
    sscanf(string[i], "%s %s %s %s" ,str1, str,str2, str3); 
    if(str[0]=='0' && str[1] == '0' && str[2]!= 'd') { 
    temp[i] = "NOP"; 
    count++; 
    } 
    if(str[0]=='0'&& str[1] == '6' && str[2]!= 'd') { 
    sprintf(temp[i],"%s,%s" , "MVI B", str2); 
    count = count+2; 
    } 

    if(str[0]=='0'&& str[1] == '7' && str[2]!= 'd') { 
    temp[i] = "RLC"; 
    count++; 
    } 

L'erreur est occasionnelle - cela ne se produit pas toujours. Et cela se produit généralement quand il y a un appel à sprintf. Ah oui! Et ci-dessous est le fichier txt je charge en tant qu'exemple:

0000 21a 11r 00r 
0003 7Ea 
0004 21a 12r 00r 
0007 46a 
0008 80a 
0009 21a 13r 00r 
000C 77a 
000D 3Ea 01a 
000F 3Da 
0010 76a 
0011 0Ad 
0012 03d 
0013 01d 

Juste vu quelque chose de nouveau. voici la fenêtre de compilation je reçois:

[email protected]:~/Desktop$ ./paraler 
0000 21a 11r 00rValor de l: 16 

Valor de l: 1 
0003 7Ea 
Valor de l: 9 
0004 21a 12r 00rValor de l: 16 

Valor de l: 1 
0007 46a 
Valor de l: 9 
0008 80a 
Valor de l: 9 
0009 21a 13r 00rValor de l: 16 

Valor de l: 1 
000C 77a 
Valor de l: 9 
000D 3Ea 01a 
Valor de l: 13 
000F 3Da 
Valor de l: 9 
0010 76a 
Valor de l: 9 
0011 0Ad 
Valor de l: 9 
0012 03d 
Valor de l: 9 
0013 01d 
Valor de l: 9 
string:0000 21a 11r 00r 
string: 

string:0003 7Ea 

string:0004 21a 12r 00r 
string: 

string:0007 46a 

string:0008 80a 

string:0009 21a 13r 00r 
string: 

string:000C 77a 

string:000D 3Ea 01a 

string:000F 3Da 

string:0010 76a 

string:0011 0Ad 

string:0012 03d 

string:0013 01d 

Segmentation fault 

La chose étrange est que je reçois des espaces vides du tableau de chaînes ... At-il quelque chose à voir avec l'erreur?

+0

Avez-vous essayé d'exécuter votre code dans un débogueur? – nmichaels

+0

L'étape 1 serait de remplacer le sprintf dangereux avec le snprintf de sécurité. –

+0

Veuillez faire quelque chose au sujet de la mise en forme de votre code. L'indentation dans le deuxième bit semble foiré. – JeremyP

Répondre

0

Il y a quelques problèmes que je vois immédiatement:

modifier le premier point pourrait ne pas appliquer à votre environnement, mais vous devez garder à l'esprit

  • Vous essayez de créer char *temp[numLinHas] de un entier dont la valeur sera déterminée au moment de l'exécution. Ceci est autorisé dans C99, ou peut être fourni via une extension de compilateur, mais dans les anciennes normes C, les tailles de tableau doivent être connues au moment de la compilation. Votre code peut vraiment faire cela:

    int numLinHas = 0; 
    char *temp[numLinHas]; 
    
  • Un autre problème est que lorsque vous faites sprintf, vous essayez de copier quelque chose dans temp sans allouer de la mémoire pour le pointeur pour stocker la chaîne.

+0

A partir de C99, il est possible de créer un tableau dont la taille n'est pas connue avant l'exécution, c'est donc un code C99 légal. Votre deuxième point à propos de chaque élément de «temp» n'ayant pas été attribué est valide. –

+0

@John - merci de me le rappeler, je me suis souvenu que C99 a une telle facilité. Il pourrait ou non s'appliquer à l'OP, car il n'a pas mentionné son compilateur. – birryree

+0

Désolé! J'ai oublié de dire que j'utilise gcc pour compiler – Marcos

1

allouent la mémoire pour chaque temp[i] vous avant d'appeler sprintf? Sinon, il y a votre problème.

if (!strncmp(str, "06", 2) && str[2] != 'd') 
{ 
    temp[i] = malloc(5 + strlen(str2) + 2); // Thanks, philippe 
    if (temp[i]) 
    sprintf(temp[i], "%s,%s", "MVI B", str2); 
} 

Bien que maintenant vous devez garder une trace des éléments de temp ont été attribués avec malloc afin que vous puissiez les libérer plus tard.

Modifier

À la fin de votre programme, vous pouvez faire une boucle à travers le réseau temp et vérifier le contenu de chaque élément contre la principale partie de votre chaîne ci-dessus, et si elles correspondent, désaffecter cet élément en utilisant free:

for (i = 0; i < numLinhas; i++) 
{ 
    if (strcnmp(temp[i], "MVI B", strlen("MVI B")) == 0) 
    free(temp[i]); 
} 

Vous n'avez pas besoin de faire cela pour les éléments du tableau qui ont été affectés « NOP » ou « RLC »; dans ces cas, vous avez simplement copié l'adresse de la chaîne littérale à l'élément de tableau. Aucune nouvelle mémoire n'a été allouée pour ces éléments, vous n'avez donc pas à vous soucier de les désallouer.

+0

J'ai changé cela sur tous les sprints que j'ai eu, mais je reçois toujours Segfault .. Et j'ai même changé le sprint à snprint pour être saffer ... – Marcos

+0

Devrait être 'temp [i] = malloc (5 + strlen (str2) + 2); 'pour représenter la virgule au format sprintf je suppose. – philant

+0

Wow! Merci beaucoup! Cela a vraiment réglé le problème que j'avais! – Marcos

0
if(str[0]=='0'&& str[1] == '6' && str[2]!= 'd') { 
    /* allocate memory to store instruction - to be freed later */ 
    temp[i] = malloc(5 + strlen(str2) + 2); /* +2 for the comma */ 
    sprintf(temp[i],"%s,%s" , "MVI B", str2); 
    count = count+2; 
    } 

Le problème survient lorsqu'un mnémonique commençant par 06 et ne se terminant pas par d est rencontré; le sprintf() écrit dans une zone non allouée car temp [i] est non initialisé. Vous devez allouer de l'espace pour stocker le résultat de sprintf.

+0

où devrais-je faire cela? avant sprintf ou quand je déclare le tableau char temp []? – Marcos

+0

l'utilisation de snprintf corrige-t-elle cela? – Marcos

+0

Non, snprintf() ne changera rien ici. temp est un tableau de pointeurs. C'est très bien avec NOP et RLC que vous attribuez un pointeur à la chaîne "RLC" ou "NOP" à temp [i]. Avec MVI, vous devez allouer suffisamment d'espace pour stocker la chaîne "MVI B, n". – philant