为什么以下代码导致分段错误? (我正在尝试创建两个大小相同的矩阵,一个用静态,另一个用动态分配)
#include <stdio.h>
#include <stdlib.h>
//Segmentation fault!
int main(){
#define X 5000
#define Y 6000
int i;
int a[X][Y];
int** b = (int**) malloc(sizeof(int*) * X);
for(i=0; i<X; i++){
b[i] = malloc (sizeof(int) * Y);
}
}
奇怪的是,如果我注释掉其中一个矩阵定义,那么代码运行正常。像这样:
#include <stdio.h>
#include <stdlib.h>
//No Segmentation fault!
int main(){
#define X 5000
#define Y 6000
int i;
//int a[X][Y];
int** b = (int**) malloc(sizeof(int*) * X);
for(i=0; i<X; i++){
b[i] = malloc (sizeof(int) * Y);
}
}
或
#include <stdio.h>
#include <stdlib.h>
//No Segmentation fault!
int main(){
#define X 5000
#define Y 6000
int i;
int a[X][Y];
//int** b = (int**) malloc(sizeof(int*) * X);
//for(i=0; i<X; i++){
// b[i] = malloc (sizeof(int) * Y);
//}
}
我在32位计算机上运行Linux上的gcc。
编辑:检查malloc()是否成功:
#include <stdio.h>
#include <stdlib.h>
//No Segmentation fault!
int main(){
#define X 5000
#define Y 6000
int i;
int a[X][Y];
int* tmp;
int** b = (int**) malloc(sizeof(int*) * X);
if(!b){
printf("Error on first malloc.\n");
}
else{
for(i=0; i<X; i++){
tmp = malloc (sizeof(int) * Y);
if(tmp)
b[i] = tmp;
else{
printf("Error on second malloc, i=%d.\n", i);
return;
}
}
}
}
当我运行时没有打印出任何东西(当然希望“分段错误”)
答案 0 :(得分:6)
您的a
变量在32位系统上需要5000 * 6000 * 4 = 120 MB的堆栈空间。这可能违反了某些限制,导致分段错误。
此外,malloc()
当然可能会在某些时候失败,这可能会让您取消引用NULL
指针。
答案 1 :(得分:2)
尝试在GCC中增加堆和堆栈限制:
gcc -Wl,--stack=xxxxx -Wl,--heap=yyyyy
答案 2 :(得分:2)
您遇到分段错误,这意味着您的程序正在尝试访问尚未分配给其进程的内存地址。数组a
是一个局部变量,因此从堆栈中分配了内存。正如unwind
指出a
需要120 MB的存储空间。这几乎肯定比操作系统分配给您的进程的堆栈空间大。一旦for循环离开堆栈的末尾,就会出现分段错误。
在Linux中,堆栈大小由操作系统而不是编译器控制,因此请尝试以下操作: -
$ ulimit -a
在回复中,您应该看到如下所示的行: -
stack size (kbytes) (-s) 10240
这意味着每个进程都可以获得10Mbyte的存储空间,远远不足以满足大型阵列的需求。
您可以使用ulimit -s <stack size>
命令调整堆栈大小,但我怀疑它不允许您选择120Mbyte堆栈大小!
最简单的解决方案是使a
成为全局变量而不是局部变量。
答案 3 :(得分:1)
这些是相当大的分配。您是否尝试过检查以确保malloc()成功?
您可以对所有数组使用malloc(),并检查以确保每次都成功。
答案 4 :(得分:1)
堆栈溢出(如何合适!)会导致分段错误,这就是你在这里看到的。
在第三种情况下,堆栈指针被移动到无效的地址,但由于程序随后退出,因此不会被用于任何地址。如果你在堆栈分配后进行任何操作,你应该得到一个段错误。
答案 5 :(得分:1)
也许编译器只是将堆栈指针更改为某个大值但从不使用它,因此永远不会导致内存访问冲突。
尝试在第三个示例中初始化A的所有元素?您的第一个示例尝试在堆栈上的A之后分配B,并且访问高(在第一个分配给B)的堆栈可能是导致段错误的原因。
答案 6 :(得分:0)
你的第三个代码也不起作用(至少在我的系统上)。
尝试将内存分配给堆上的数组a
而不是(当维度很大时)。
答案 7 :(得分:0)
两个矩阵都不符合记忆的限制。您一次只能分配一个。
如果您将Y定义为3000而不是6000,则您的程序不应发出segfault。