【发布时间】:2011-08-30 09:43:23
【问题描述】:
我对这个很迷茫,希望这里有人能提供帮助。
我的应用程序包含数百个评估数字代码的函数(每个源在 5MB 范围内),我使用 std::map 来管理函数指针。
显然发生的事情是,当我尝试将参数传递给通过指向它的指针访问的函数之一时,我得到了堆栈溢出:
gdb 输出:
Program received signal SIGSEGV, Segmentation fault.
0x0000000001ec0df7 in xsectiond149 (sme=Cannot access memory at address 0x7fffff34b888
) at xsection149.c:2
2 Poly3 xsectiond149(std::tr1::unordered_map<int, Poly3> & sme,
EvaluationNode::Ptr ti[], ProcessVars & s)
并且 xsection149.c:2 仅具有用于定义函数的左大括号。
/proc/<pid>/map 为进程显示最接近触发错误的地址的地址范围仅这一行:
7ffffff74000-7ffffffff000 rw-p 7ffffff73000 00:00 0 [stack]
所以上述错误中的地址超出范围。
现在我的问题是:我该如何解决这个问题?我不知道我可以在堆上分配什么......
在我的主程序中发生的唯一想法是:
// A map containing O(10^4) Poly3 (struct with 6 doubles)
tr1::unordered_map<int, Poly3> smetemp;
// populates smetemp
computeSMEs(smetemp);
// Map of function pointers of type, O(10^3) elements
tr1::unordered_map<int, xsdptr> diagfunctions = get_diagram_map();
这怎么会溢出堆栈??
编辑:我尝试在 valgrind 中运行它,这是我得到的错误,谷歌没有提供任何有意义的信息:
valgrind: m_debuginfo/storage.c:417 (vgModuleLocal_addDiCfSI):
Assertion 'cfsi.len < 5000000' failed.
==491== at 0x38029D5C: ??? (in /usr/lib64/valgrind/memcheck-amd64-linux)
EDIT2:将函数反汇编到它失败的点(0x0000000001ec0df7)给我:
Dump of assembler code for function xsectiond149(std::tr1::unordered_map<int, Poly3, std::tr1::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, Poly3> >, false>&, std::vector<boost::shared_ptr<EvaluationNode>, std::allocator<boost::shared_ptr<EvaluationNode> > >&, ProcessVars&):
<...+0>: push %rbp
<...+1>: mov %rsp,%rbp
<...+4>: push %r15
<...+6>: push %r14
<...+8>: push %r13
<...+10>: push %r12
<...+12>: push %rbx
<...+13>: sub $0xc96b58,%rsp
<...+20>: mov %rdi,%rbx
<...+23>: mov %rsi,-0xc8b078(%rbp) // this instr fails
函数的前几行如下:
Poly3 xsectiond149(std::tr1::unordered_map<int, Poly3> & sme,
std::vector<EvaluationNode::Ptr> & ti,
ProcessVars & s)
{
Poly3 sum(0,0,0,-2);
Poly3 prefactor, expr;
// CF*CA^2*NF*NA^(-2)
double col0 = 0.5625000000000000000000000000;
prefactor = col0*ti[0]->value()*s.Qtpow2*s.epow2*s.gpow6;
expr = (128*(s.p1p2*sme[192]*s.mt - s.p1p2*sme[193]*s.mt +
1/2.*s.p1p2*sme[195]*s.mt - 1/2.*s.p1p2*sme[196]*s.mt -
s.p1p2*sme[201]*s.mt + s.p1p2*sme[202]*s.mt +
1/2.*s.p1p2*sme[210]*s.mt - 1/2.*s.p1p2*sme[211]*s.mt -
1/4.*s.p1p2*sme[216]*s.mt + 1/4.*s.p1p2*sme[217]*s.mt -
s.p1p2*sme[219]*s.mt + s.p1p2*sme[220]*s.mt -
1/8.*s.p1p2*sme[1209]*s.mt + 1/8.*s.p1p2*sme[1210]*s.mt +
1/2.*s.p1p2*sme[1215]*s.mt - 1/2.*s.p1p2*sme[1216]*s.mt +
// .....
}
(注意我在实验过程中更改了函数的签名)
任何人都可以解决这里发生的事情吗?您需要哪些附加信息?抱歉,我几乎没有使用 asm 的经验。
EDIT3:
使用ulimit -s <size> 增加堆栈大小就可以了。谢谢大家的帮助!
【问题讨论】:
-
堆栈溢出或访问冲突?似乎是后者,而不是前者。
-
我很想看看引入此 segv 的签入内容。
-
@GMan:我认为这是堆栈溢出,很难说。实际上在调用
xsectiond149(...)之前访问smetemp可以正常工作,所以我想这是将参数传递给函数的问题。 -
看起来像一个简单的堆栈溢出。不要在你的小线程堆栈上声明巨大的变量 =P
-
@bbtrb,如果你有 5megs 的源代码可以使用,我认为这一切都在源代码控制之下。而且你不只是结束了 5 兆的源,它肯定必须在过去的某个时候工作。那么,在它工作和失败之间发生了什么变化?找到那个签入,希望它会更容易发现问题。 :)
标签: c++ stack-overflow function-pointers