2017-08-10 135 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