C程序在Linux命令行中导致分段错误,但在gdb中正常退出



我编写了以下C程序来打印整数的每个字节:

#include <stdio.h>
#include <stdlib.h>
union bytes
{   int number;
char bytes[sizeof(int)];
};
int main(int argc, char **argv)
{   for (int i=1; i < argc; i++)
{
int* x;
*x = atoi(argv[i]);
union bytes bytes_of_x;
bytes_of_x.number = *x;
for (int j=0; j < sizeof(int); j++)
{
unsigned char b = *((unsigned char*)x + j);
bytes_of_x.bytes[j] = b;
}
for (int k=0; k < sizeof(int); k++)
{
printf("Byte %d = %xn", k+1, bytes_of_x.bytes[k]);
}
}
return 0;
}

它编译得很好,没有任何警告,但当我在命令行上运行它时(使用./progname integer(,它返回了一个分段错误。

我用几个不同的输入在gdb中运行程序,但每次都正常退出。

既然gdb没有识别任何错误,我应该如何识别分段错误的来源?

您尚未为x分配任何内存。这个变量是一个指针,但您使用它时没有为它分配任何有效的内存。

x需要malloc内存,如下所示:

int *x = malloc(sizeof(int));

然后记住free,如下所示:

free(x);

在每次CCD_ 5循环迭代结束时。

然而,我质疑是否需要以这种方式实际声明x。为什么不先将CCD_ 7参数分配给堆栈上声明的CCD_;然后初始化第二个变量指向它,如下所示:

int y = atoi(argv[i]);
int *x = &y;

此外,你说你的程序"编译得很好,没有任何警告">。这向我表明,您的代码至少没有使用一些基本编译标志进行编译,这些标志会警告您x未初始化。例如,使用gcc:

gcc -Wall program.c

会很容易发现这个错误,而

gcc -Wall -Werror program.c

会阻止编译";成功的";总共

请阅读编译器的手册页面,了解更多关于编译标志的信息,这将为您节省时间;麻烦

另外:另一个有用的工具是valgrind,它在检测未初始化的变量、内存泄漏等方面做得很好。

它编译得很好,没有警告

您需要打开其他警告,或者需要更好的编译器。

使用GCC 8.3.0:

gcc -g t.c -Wall
t.c: In function ‘main’:
t.c:12:12: warning: ‘x’ may be used uninitialized in this function [-Wmaybe-uninitialized]
*x = atoi(argv[i]);
~~~^~~~~~~~~~~~~~~
gcc -g t.c -Wall -Wextra
t.c: In function ‘main’:
t.c:15:25: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
for (int j=0; j < sizeof(int); j++)
^
t.c:20:25: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
for (int k=0; k < sizeof(int); k++)
^
t.c:12:12: warning: ‘x’ may be used uninitialized in this function [-Wmaybe-uninitialized]
*x = atoi(argv[i]);
~~~^~~~~~~~~~~~~~~

正如其他答案已经说过的,您正在通过未初始化的指针进行写入,这会导致未定义的行为。UB的意思是:任何事情都可能发生,包括程序似乎在一台机器上工作,但在另一台计算机上不工作,或者在GDB下工作而不在GDB外工作,反之亦然。

由于gdb无法识别任何错误,我应该如何识别分段错误的来源?

您可以使用GDB进行死后调试:

# Set core dump size to be unlimited
ulimit -c unlimited
# Generate a core dump
./a.out 42
Segmentation fault (core dumped)
gdb a.out core    # now use GDB to debug the crash.

最新更新