如何解决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 = %x\n",k+1,bytes_of_x.bytes[k]);
}
}
return 0;
}
它编译得很好,没有警告,但是当我在命令行上运行它时(使用 ./progname 整数),它返回了一个分段错误。
我用几个不同的输入在 gdb 中运行程序,但每次它都正常退出。
由于 gdb 未识别任何错误,我应该如何确定分段错误的来源?
解决方法
您尚未为 x
分配任何内存。这个变量是一个指针,但你在使用它时没有分配任何有效的内存来使用。
您需要像这样为 malloc
分配 x
内存:
int *x = malloc(sizeof(int));
然后记得free
它,就像这样:
free(x);
在每次 for
循环迭代结束时。
但是,我怀疑是否需要以这种方式实际声明 x
。为什么不先将 argv[i]
参数分配给在堆栈上声明的 int
变量,然后初始化第二个变量以指向它,如下所示:
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.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。