2017-08-10 4 views
-2
#include <stdio.h> 


int main(void) 
{ 
    /* an array with 5 rows and 2 columns*/ 
    char* a[5][2]; 
    int y, p; 

    for(y = 0; y < 5; y++) 
    { 
     for(p = 0; p < 2; p++) 
     { 
      scanf("%s", a[y][p]); 
     }      
    }  

    int i, j; 

    /* output each array element's value */ 
    for (i = 0; i < 5; i++) 
    {    
     for (j = 0; j < 2; j++) 
     { 
     printf("a[%d][%d] = %s\n", i,j, a[i][j]); 
     } 
    } 

    return 0;   
} 

je reçois un en tant que sortie faute Segmentation de ce programme après l'insertion 2 chaînes. Quelqu'un peut-il me dire ce qui ne va pas avec mon code?Segmentation fault

+0

Étape 1: Que dit votre débogueur? – tadman

+2

Indice: Vos tampons de caractères 'a' ne sont jamais initialisés, alors où' scanf' met-il ces données? Probablement à un endroit de pointeur aléatoire et de faire exploser votre programme. – tadman

+0

Autre indice: vous avez besoin d'une ligne 'a [y] [p] = malloc (X);' juste avant 'scanf ("% s ", a [y] [p]);', où 'X' est le longueur de la chaîne à lire plus 1. – DyZ

Répondre

2

Problème:

Vous déclarer 10 pointeurs non initialisées ici:

char* a[5][2]; 

Et puis essayer de les remplir avec des données:

scanf("%s", a[y][p]); 

Ceci est faux. Vous devez allouer de la mémoire avant de copier des données.

Solution:

je referais ce d'une manière plus sexy, mais la solution rapide serait:

#define MAX_LEN 100 

char a[5][2][MAX_LEN]; 

/* ... */ 

scanf("%s", a[y][p][0]); 
+1

'scanf ("% s ", a [y] [p] [0]);' -> 'scanf ("% 99s ", a [y] [p] [0]);' pour arrêter les dépassements de tampon –

+0

@ EdHeal, c'est vrai. De plus, tous les compilateurs ne garantissent pas que les variables sont mises à zéro: 'memset (a, 0, sizeof (a));' –

+0

@Andrejs Cainikovs - Non, ce n'est pas la vérité. Il y a deux cas: les variables non initialisées avec stockage statique (variables globales et variables locales statiques) sont garanties à zéro, toutes les variables automatiques non initialisées sont garanties de ne pas être initialisées :). –

0

Juste un soupçon sur l'aide Dépanner. J'espère que cela aidera les futurs lecteurs qui sont nouveaux pour les pointeurs.

Une meilleure façon de résoudre un problème de segmentation est de l'exécuter avec un débogueur tel que gdb.

par exemple compiler votre programme avec gdb (Vous devez GDB installé sur votre hôte)

gcc -ggdb Test.c -o Test 

Lancez ensuite avec gdb

gdb ./Test 

Dans votre cas, vous verrez une sortie comme celui-ci . Cela va à l'invite gdb. Ensuite, tapez run ou r, il exécutera le programme. Ensuite, il demande une entrée. Tapez votre valeur d'entrée. Ensuite, l'erreur de segmentation se produit. Vous pouvez maintenant voir votre backtrace en tapant backtrace ou bt. Vous pouvez voir quelle ligne provoque votre accident. Vous pouvez voir le code par list. Vous pouvez accéder à n'importe quelle ligne en tapant list <line>. Passez par un GDB Guide pour découvrir plus de commandes.

Il essaie d'accéder à un pointeur, probablement invalide, c'est pourquoi il plante. Ensuite, découvrez pourquoi c'est invalide. Vous ne l'avez probablement pas initialisé ou n'avez pas alloué de mémoire. Donc la solution la plus simple serait de le déclarer comme un tableau (plutôt qu'un tableau de pointeurs) comme @Andrewjs mentionné dans sa réponse.

Reading symbols from /tmp/Examples/Test...done. 
(gdb) run 
Starting program: /tmp/Examples/Test 
for 1 
for 2 
10 

Program received signal SIGSEGV, Segmentation fault. 
0x005c5c3d in _IO_vfscanf_internal (s=0x6d1420, format=0x804867e "%s", argptr=0xbfffe984 "\020\204\004\b", errp=0x0) at vfscanf.c:840 
840       *str++ = c; 
(gdb) backtrace 
#0 0x005c5c3d in _IO_vfscanf_internal (s=0x6d1420, format=0x804867e "%s", argptr=0xbfffe984 "\020\204\004\b", errp=0x0) at vfscanf.c:840 
#1 0x005cebbb in __scanf (format=0x804867e "%s") at scanf.c:35 
#2 0x0804850d in main() at Test.c:16 <-- Your program's last call 
(gdb) list 
835      } 
836  #else 
837      /* This is easy. */ 
838      if (!(flags & SUPPRESS)) 
839       { 
840       *str++ = c; <-- Crash point 
841       if ((flags & MALLOC) 
842        && (char *) str == *strptr + strsize) 
843        { 
844        /* Enlarge the buffer. */ 
(gdb) 

Pour le débogage d'applications avant This may help