奇怪的堆栈溢出?
我遇到了一个奇怪的情况,将一个指针传递给struct {}定义中定义的非常大的数组,这个数组大小约为34MB。简而言之,该伪代码如下所示:奇怪的堆栈溢出?
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);
}
代码编译罚款,但是当我尝试运行它,我会在下面{Read_Config_File()获得一个SIGSEGV。
(gdb) run
...
Program received signal SIGSEGV, Segmentation fault.
0x0000000000407d0a in Read_Config_File (the_config=Cannot access memory at address 0x7ffffdf45428
) at ../src/config_parsing.c:763
763 {
(gdb) bt
#0 0x0000000000407d0a in Read_Config_File (the_config=Cannot access memory at address 0x7ffffdf45428
) at ../src/config_parsing.c:763
#1 0x00000000004068d2 in main (argc=1, argv=0x7fffffffe448) at ../src/main.c:148
我一直都在用小数组来完成这种事情。奇怪的是,0x7fffffffe448 - 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
错误信息都指向我重挫堆栈指针,但)我从来没有穿过一个在函数的入口和崩溃运行B)我传递指针,而不是实际的数组。
有人可以帮我解决这个问题吗?我在一个运行内核2.6.18和gcc 4.1.2的64位CentOS盒子上。
谢谢!
马特
你已经通过将这些巨大的config_t结构体中的一个分配到它上面而炸毁了堆栈。 gdb输出中有证据的两个堆栈指针0x7fffffffe448和0x7ffffdf45428对此非常有帮助。
$ gdb
GNU gdb 6.3.50-20050815 ...blahblahblah...
(gdb) p 0x7fffffffe448 - 0x7ffffdf45428
$1 = 34312224
您的〜34MB常量与config_t结构的大小相匹配。系统默认情况下不会为您提供太多的堆栈空间,因此无论是将对象移出堆栈还是增加堆栈空间。
有没有一种类似“lint”的工具可以告诉我一个函数会吞噬多少堆栈?事后看来,现在很明显的是故障是什么,但如果存在这样的问题,我很乐意知道。 – tranzmatt
对于运行时检查,gcc具有-fstack-limit- *,但我知道没有任何警告编译时的堆栈分配过大。 –
简短的回答是,必须有声明为一个局部变量某处config_t
,它会把它的堆栈。可能是一个错字:CONFIG声明之后丢失*
。
这是问题所在。我忘记了在干扰数组之前,我在函数中保留了一个临时的config_t结构副本。我在其他地方移动了阵列,现在它不会发生故障。谢谢。 – tranzmatt
发布伪代码只会让你伪造答案。魔鬼在细节中,他们可能都很重要。 –
我们可否看到'Read_Config_File'的来源?这就是问题出现的地方,在你消失的地方。 – Borealid
您不测试可能失败的calloc()的返回值。 –