2017-08-10 143 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;   
} 

插入2串後,我已經得到一個分段故障作爲該計劃的輸出。任何人都可以告訴我我的代碼有什麼問題嗎?分段故障

+0

第1步提前調試:什麼是您的調試器說? – tadman

+2

提示:您的'a'字符緩衝區永遠不會被初始化,那麼'scanf'在哪裏放置這些數據?可能在一些隨機指針位置並炸燬你的程序。 – tadman

+0

另一個提示:在'scanf(「%s」,a [y] [p])之前需要一行'a [y] [p] = malloc(X);'',其中'X'是要讀取的字符串的長度加上1. – DyZ

回答

2

問題:

你在這裏宣佈10個未初始化的指針:

char* a[5][2]; 

然後試圖用數據來填充他們:

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

這是不對的。您需要在複製數據之前分配內存。

解決方案:

我會做到這一點更性感的方式,但快速的解決辦法是:

#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]);'停止緩衝區溢出 –

+0

@EdHeal,真的。另外,並非所有編譯器都保證變量被清零:'memset(a,0,sizeof(a));' –

+0

@Andrejs Cainikovs - 不,這不是事實。有兩種情況 - 使用靜態存儲的未初始化變量(全局變量和靜態局部變量)保證爲零,所有未初始化的自動變量保證不被初始化:)。 –

0

上幫助排除故障只是一個提示。希望這將有助於未來的讀者誰是新的指針。

解決分段錯誤的更好方法是使用像gdb這樣的調試器來運行它。

如 使用gdb編譯程序(需要GDB安裝在主機上)

gcc -ggdb Test.c -o Test 

然後用gdb

gdb ./Test 

運行它在你的情況,你會看到這樣的輸出。它會轉到gdb提示。 然後輸入runr,它會運行該程序。然後它要求輸入。輸入您的輸入值。然後發生分段故障。現在,您可以輸入backtracebt來查看回溯。你可以看到哪一行會導致你的崩潰。您可以通過list查看代碼。你可以通過輸入list <line>去任何一行。請通過GDB Guide瞭解更多命令。

它試圖訪問一個指針,可能無效,這就是爲什麼它崩潰。然後找出爲什麼它是無效的。可能你沒有初始化它,或者沒有分配內存。所以最簡單的解決方法是將其聲明爲一個數組(而不是指針數組),就像他在答案中提到的@Andrewjs一樣。

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) 

對於應用This may help