C语言:在声明数组时获取分段错误

时间:2013-01-17 07:12:13

标签: c arrays segmentation-fault structure

以下是该方案:      我正在声明一个数组,并且不使用它在程序中的任何地方。如果我声明它的长度为100或更短,它工作正常。对于更长的长度,它给出了分段错误。我无法理解这种行为。

ATL_RAM_BUFFER_L3 an_unknown_array [128];

ATL_RAM_BUFFER_L3的结构几乎为72KB。

2 个答案:

答案 0 :(得分:4)

你正在耗尽你的堆栈,这通常是一个有限的资源,在你的情况下还不足以容纳阵列占用的大约9兆兆字节。

有几种可能的解决方案。如果您只需要一个副本,则可以在函数外部声明它(或者作为函数中的静态函数) - 这通常会使它远离堆栈并将其放入存储空间有限的区域。

或者,您可以动态分配它,并确保正确管理它。

您可能还可以根据环境配置更大的堆栈大小。


举例来说,以下bash脚本将计算出(默认)环境中可以在堆栈上分配的数据量:

((sz = 0))
((delta = 1000000))
while [[ ${delta} -gt 0 ]]; do
    while true; do
        sleep 1
        ((sz += delta))
        printf "Trying ${sz} ... "
        rm -f qq.c
        echo "#include <stdio.h>" >>qq.c
        echo "int main (void) {" >>qq.c
        echo "    char buff[${sz}];" >>qq.c
        echo "    puts (\"hello\");" >>qq.c
        echo "    return 0;" >>qq.c
        echo "}" >>qq.c
        gcc -o qq qq.c
        trap 'echo "segfault!"' CHLD
        rm -f flagfile
        ( bash -c './qq >flagfile 2>/dev/null' ) >/dev/null 2>&1
        if [[ "$(cat flagfile)" == "hello" ]]; then
            echo "okay"
        else
            echo "crashed"
            ((sz -= delta))
            break
            fi
    done
    ((delta = delta / 10))
done

它的工作原理是构建一个以下形式的C程序:

#include <stdio.h>
int main (void) {
    char buff[XYZZY];
    puts ("hello");
    return 0;
}

其中XYZZY逐渐改变,以查看程序首先因缺少堆栈空间而崩溃的位置。我环境中的输出(CygWin)是这样的:

Trying 1000000 ... okay
Trying 2000000 ... okay
Trying 3000000 ... crashed
Trying 2100000 ... crashed
Trying 2010000 ... okay
Trying 2020000 ... okay
Trying 2030000 ... okay
Trying 2040000 ... okay
Trying 2050000 ... okay
Trying 2060000 ... okay
Trying 2070000 ... okay
Trying 2080000 ... crashed
Trying 2071000 ... crashed
Trying 2070100 ... crashed
Trying 2070010 ... okay
Trying 2070020 ... okay
Trying 2070030 ... okay
Trying 2070040 ... okay
Trying 2070050 ... okay
Trying 2070060 ... okay
Trying 2070070 ... crashed
Trying 2070061 ... okay
Trying 2070062 ... okay
Trying 2070063 ... okay
Trying 2070064 ... okay
Trying 2070065 ... crashed

意味着两兆字节大约是最大值。

答案 1 :(得分:0)

在运行时分配/释放本地变量的内存。它们在堆栈上创建,每个线程/进程都有一个有限的堆栈。堆栈的大小很大程度上取决于编译器和操作系统。它因系统而异。在Unix / Linux类型的系统中,程序将在发生堆栈溢出时通过分段故障。请看this document for more details on this subject

另一方面,当程序加载到内存中时,会分配全局变量的内存。如果未初始化,则在BSS部分中分配内存;如果初始化为某个值,则在数据部分中分配内存。通常,这些部分比进程的堆栈具有更多的空间。因此,通常建议全局声明大型变量/对象,以避免此问题。