C中矩阵的内存分配

时间:2010-04-15 15:05:29

标签: c pointers memory-management

为什么以下代码导致分段错误? (我正在尝试创建两个大小相同的矩阵,一个用静态,另一个用动态分配)

#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;
            }
        }
    }    
}

当我运行时没有打印出任何东西(当然希望“分段错误”)

8 个答案:

答案 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。

相关问题