3

这是场景:我正在声明一个数组,但还没有在程序中的任何地方使用它。如果我声明它的长度为 100 或更少,它工作正常。对于更大的长度,它会给出分段错误。我无法理解这种行为。

ATL_RAM_BUFFER_L3 an_unknown_array[128];

其中 ATL_RAM_BUFFER_L3 是一个将近 72KB 的结构。

4

2 回答 2

4

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

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

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

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


例如,以下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;
}

whereXYZZY逐渐更改以查看程序因堆栈空间不足而首先崩溃的位置。我的环境(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

这意味着 2 兆字节是关于它最大的地方。

于 2013-01-17T07:19:32.580 回答
0

局部变量的内存在运行时分配/释放。它们是在堆栈上创建的,每个线程/进程都有一个有限的堆栈。堆栈的大小很大程度上取决于编译器和操作系统。它因一个系统而异。在 Unix/Linux 类型的系统中,当堆栈溢出发生时,程序将通过分段错误。有关此主题的更多详细信息,请查看此文档

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

于 2013-01-17T07:31:26.873 回答