C中矩阵的内存分配

Sno*_*wtr 8 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,如果我注释掉其中一个矩阵定义,代码运行正常.像这样:

#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);
    }
}
Run Code Online (Sandbox Code Playgroud)

要么

#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);
    //}
}
Run Code Online (Sandbox Code Playgroud)

我在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;
            }
        }
    }    
}
Run Code Online (Sandbox Code Playgroud)

我运行时没有打印出任何东西(当然希望"分段故障")

unw*_*ind 6

a在32位系统上,您的变量需要5000*6000*4 = 120 MB的堆栈空间.这可能会违反某些限制,从而导致分段错误.

此外,它当然可能malloc()在某些时候失败,这可能会让你取消引用一个NULL指针.


And*_*lly 2

您遇到分段错误,这意味着您的程序正在尝试访问尚未分配给其进程的内存地址。该数组a是一个局部变量,因此从堆栈中分配内存。正如所unwind指出的a,需要 120 MB 的存储空间。这几乎肯定大于操作系统分配给进程的堆栈空间。一旦 for 循环离开堆栈末尾,就会出现分段错误。

在 Linux 中,堆栈大小由操作系统而不是编译器控制,因此请尝试以下操作:-

$ ulimit -a
Run Code Online (Sandbox Code Playgroud)

在响应中,您应该看到类似这样的一行:-

stack size (kbytes)            (-s)  10240
Run Code Online (Sandbox Code Playgroud)

这意味着每个进程获得 10MB 的存储空间,对于大型阵列来说远远不够。

您可以使用命令调整堆栈大小ulimit -s <stack size>,但我怀疑它不允许您选择 120Mbyte 堆栈大小!

最简单的解决方案是创建a全局变量而不是局部变量。