C 奇怪的堆栈溢出?

C 奇怪的堆栈溢出?,c,pointers,stack-overflow,C,Pointers,Stack Overflow,我遇到了一个奇怪的情况,将指针传递给一个结构,该结构在struct{}定义中定义了一个非常大的数组,一个大约34MB大小的浮点数组。简而言之,psuedo代码如下所示: typedef config_t{ ... float values[64000][64]; } CONFIG; int32_t Create_Structures(CONFIG **the_config) { CONFIG *local_config; int32_t number_nodes; n

我遇到了一个奇怪的情况,将指针传递给一个结构,该结构在struct{}定义中定义了一个非常大的数组,一个大约34MB大小的浮点数组。简而言之,psuedo代码如下所示:

typedef config_t{
  ...
  float values[64000][64];
} CONFIG;


int32_t Create_Structures(CONFIG **the_config)
{
  CONFIG  *local_config;
  int32_t number_nodes;

  number_nodes = Find_Nodes();

  local_config = (CONFIG *)calloc(number_nodes,sizeof(CONFIG));
  *the_config = local_config;
  return(number_nodes);
}


int32_t Read_Config_File(CONFIG *the_config)
{
    /* do init work here */
    return(SUCCESS);
}


main()
{
    CONFIG *the_config;
    int32_t number_nodes,rc;

    number_nodes = Create_Structures(&the_config);

    rc = Read_Config_File(the_config);
    ...
    exit(0);
}
代码编译得很好,但是当我尝试运行它时,我会在{underread_Config_File()下得到一个SIGSEGV

我一直在用更小的阵列做这类事情。奇怪的是,0x7FFFFFE448-0x7ffffdf45428=0x20B8EF8,或者大约是我的浮点阵列的34MB

Valgrind将给我类似的输出:

==10894== Warning: client switching stacks?  SP change: 0x7ff000290 --> 0x7fcf47398
==10894==          to suppress, use: --max-stackframe=34311928 or greater
==10894== Invalid write of size 8
==10894==    at 0x407D0A: Read_Config_File (config_parsing.c:763)
==10894==    by 0x4068D1: main (main.c:148)
==10894==  Address 0x7fcf47398 is on thread 1's stack
错误消息都指向我敲击堆栈指针,但a)我从未遇到过在函数输入时崩溃的堆栈指针,b)我传递的是指针,而不是实际的数组

有人能帮我吗?我在一个64位的CentOS机器上运行内核2.6.18和GCC4.1.2

谢谢


Matt

简单的回答是,必须有一个
config\u t
声明为局部变量,它将把它放在堆栈上。可能是一个输入错误:在某个配置声明之后缺少
*

通过在堆栈上分配一个巨大的配置结构,您已经破坏了堆栈。evid上的两个堆栈指针gdb输出0x7FFFFFE448和0x7ffffdf45428中的ence非常说明这一点

$ gdb
GNU gdb 6.3.50-20050815 ...blahblahblah...
(gdb) p 0x7fffffffe448 - 0x7ffffdf45428  
$1 = 34312224

您的~34MB常量与配置结构的大小相匹配。默认情况下,系统不会给您那么多堆栈空间,因此要么将对象移出堆栈,要么增加堆栈空间。

发布伪代码只会得到伪答案。问题在于细节,它们可能都很重要。我们可能会看到
Read_Config_File
的源代码?在您省略的块中,问题似乎就在这里。您没有测试calloc()的返回值,这可能会失败。@tranzmatt你能粘贴
读取配置文件
的源代码吗?正如@Borealid所说,还有
创建结构
读取配置文件
调用之间的代码,如果有调用的话?
读取配置文件
可能会在数组的末尾写下。这就是问题所在。我忘了我保留了一个临时副本在干扰阵列内部之前,函数中的配置结构。我将阵列移到了其他位置,现在它没有seg错误。谢谢。是否有“lint”-就像一个工具可以告诉我一个函数将吞噬多少堆栈一样?事后看来,故障是什么已经很明显了,但我很想提前知道是否存在这样的问题。gcc有-fstack limit-*用于运行时检查,但我不知道在编译时警告过大的堆栈分配。
$ gdb
GNU gdb 6.3.50-20050815 ...blahblahblah...
(gdb) p 0x7fffffffe448 - 0x7ffffdf45428  
$1 = 34312224