我想做的是创建一个10x10数组,只打印对角线上的值,它目前正在分段,所以我有几个问题。1.使用终端外壳在Mac上调试segfault最简单的方法是什么?2.我正试图找出这个函数在哪里出错?我尝试在values=malloc上面添加一个简单的printf语句。。。我想它甚至没有走那么远。
int **values;
int i, j;
values = malloc(10 * sizeof(int *));
for (i = 0; i < 10; i++){
for (j = 0; j < 10; j++){
values[i][j] = i * j;
}
}
for (i = 0; i < 10; i++)
printf("%d ", values[i][i]);
printf("n");
如果您在运行某个版本的OS X的Mac上,则应该同时安装gcc和gdb。如果没有,它们很容易下载和安装。我在Linux系统上运行,但下面的步骤和输出在OS X上应该类似。
为了在调试器中查看源代码,您必须使用-g
选项进行编译:gcc -o myprog -g myprog.c
。否则,您将只能看到生成的机器代码。
在这一点上,您可以正常运行程序,让它转储一个核心文件,您将加载到gdb中,也可以在gdb中启动程序,逐行执行。
我冒昧地拿走了你的代码,并从中创建了一个完整的程序:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int **values;
int i, j;
values = malloc(10 * sizeof(int *));
for (i = 0; i < 10; i++){
for (j = 0; j < 10; j++){
values[i][j] = i * j;
}
}
for (i = 0; i < 10; i++)
printf("%d ", values[i][i]);
printf("n");
return 0;
}
我们将在启用调试的情况下构建它:
$ gcc -o example -g -std=c99 -pedantic -Wall -Werror example.c
并在gdb:中启动
$ gdb example
GNU gdb (GDB) SUSE (7.1-8.9.1)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-suse-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/fbgo448/prototypes/coredump/example...done.
(gdb)
我们要做的第一件事是在main
设置一个断点;这将导致程序在进入主功能时立即暂停:
(gdb) break main
Breakpoint 1 at 0x4005a0: file example.c, line 9.
现在,我们将启动在gdb环境中运行的程序;它将运行到下一个断点:
(gdb) r
Starting program: /home/fbgo448/prototypes/coredump/example
Breakpoint 1, main () at example.c:9
9 values = malloc(10 * sizeof(int *));
你可以一次执行一行,就像这样:
(gdb) n
10 for (i = 0; i < 10; i++){
您可以检查变量或任意内存位置的内容:
(gdb) p values
$1 = (int **) 0x501010
(gdb) p *values
$2 = (int *) 0x0
(gdb) x/1x 0x501010
0x501010: 0x00000000
(gdb) x/1b 0x501010
0x501010: 0x00
(gdb) x/10b 0x501010
0x501010: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x501018: 0x00 0x00
(gdb) x/10x 0x501010
0x501010: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x501018: 0x00 0x00
希望你已经看到了问题,但如果没有,我们可以"继续"程序,让它运行直到失败:
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005e3 in main () at example.c:12
12 values[i][j] = i * j;
您在尝试分配values[i][j]
时遇到segfault。让我们再来看看:
(gdb) p i
$3 = 0
(gdb) p j
$4 = 0
(gdb) p values
$5 = (int **) 0x501010
(gdb) p values[i]
$6 = (int *) 0x0
(gdb) p values[i][j]
Cannot access memory at address 0x0
其他人指出了这个问题;您为int
分配了足够的空间来容纳10个指针,但没有为那些指向到的指针分配任何空间。您在分配过程中错过了一个步骤:
values = malloc( 10 * sizeof *values ); // sizeof *values == sizeof (int *)
if ( values )
{
for ( i = 0; i < 10; i++ )
{
values[i] = malloc( 10 * sizeof *values[i] ); // sizeof *values[i] == sizeof (int)
if ( values[i] )
{
for (j = 0; j < 10; j++ )
{
values[i][j] = i * j;
}
}
}
}
gdb是一个相当强大的调试器,尽管使用起来有点麻烦。
您需要同时分配"列"one_answers"行"。现在您只分配指向整数的指针,还需要分配整数本身。
int **values;
int i, j;
values = (int**)malloc(10 * sizeof(int *));
for(i = 0; i < 10; i++){
values[i] = (int*)malloc(10 * sizeof(int)); //Small edit.
}
for (i = 0; i < 10; i++){
for (j = 0; j < 10; j++){
values[i][j] = i * j;
}
}
for (i = 0; i < 10; i++)
printf("%d ", values[i][i]);
printf("n");
我对Mac不太了解,但我确信你可以使用GDB。使用调试选项编译程序以创建包含调试信息的可执行文件,当程序崩溃时,它将生成核心转储。打开这个核心转储与gdb和bon食欲。
只要指针的地址指向不允许的内存段,就会发生分段故障。这种情况发生在未初始化的情况下。大部分时间垃圾值都会导致此类故障。
为了避免这种情况,请使用calloc而不是malloc(),因为calloc()
分配内存并初始化为零。
此外,你必须为第二维度分配空间。
int **values;
int i, j;
values = (int**)calloc(10 * sizeof(int *));
for(i = 0; i < 10; i++){
values[i] = (int*)calloc(10 * sizeof(int)); //Small edit.
}
for (i = 0; i < 10; i++){
for (j = 0; j < 10; j++){
values[i][j] = i * j;
}
}
for (i = 0; i < 10; i++)
printf("%d ", values[i][i]);
printf("n");
更改代码是最简单的方法。方法如下:
int i, j;
values = malloc(10 * sizeof(int*));
for (i = 0; i < 10; i++)
{
values[i] = malloc(10 * sizeof(int));
for (j = 0; j < 10; j++)
{
values[i][j] = i * j;
}
}
完成后,不要忘记free
:
int i;
for (i = 0; i < 10; i++)
{
free(values[i]);
}
free(values);