【问题标题】:C Language: Getting Segmentation fault on Declaring an arrayC 语言:在声明数组时出现分段错误
【发布时间】:2012-12-31 16:28:13
【问题描述】:

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

ATL_RAM_BUFFER_L3 an_unknown_array[128];

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

【问题讨论】:

  • 全局声明或动态分配。您说的是超过 9MB 的静态分配,这可能超出了您的堆栈大小。
  • 可能是内存空间不足以容纳 128*72 KB
  • 它仍然在堆栈上分配,因此任何后续分配都将超出范围。
  • 附带说明,这是什么结构,大小为 72KB。?
  • @CashifIlyas 全局声明将变量放在加载图像的 DATA 段中,并且超出了执行线程在本地调用堆栈上可以访问的有限空间。

标签: c arrays segmentation-fault structure


【解决方案1】:

您正在耗尽通常是有限资源的堆栈,在您的情况下不足以容纳您的阵列占用的大约 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

意思是 2 MB 大约是它的最大值。

【讨论】:

  • @CashifIlyas 因为静态缓冲区不会在堆栈上
  • @Cashif,因为这给了它静态存储持续时间,这通常将它放入比堆栈更大容量的区域。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-03
    • 2016-12-05
    • 2016-06-03
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    相关资源
    最近更新 更多