C++ 堆栈溢出和函数指针
我对这件事很迷茫,希望这里有人能帮忙 我的应用程序由数百个计算数字代码的函数组成(每个源代码都在5MB范围内),我使用C++ 堆栈溢出和函数指针,c++,stack-overflow,function-pointers,C++,Stack Overflow,Function Pointers,我对这件事很迷茫,希望这里有人能帮忙 我的应用程序由数百个计算数字代码的函数组成(每个源代码都在5MB范围内),我使用std::map到函数指针来管理这些函数。 显然,当我试图将一个参数传递给其中一个函数时,会出现堆栈溢出,该函数由指向它的指针访问: gdb输出: Program received signal SIGSEGV, Segmentation fault. 0x0000000001ec0df7 in xsectiond149 (sme=Cannot access memory at
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)
因此,上述错误中的地址超出了范围
现在我的问题是:如何解决这个问题?我不知道我能在堆上分配什么
在我的主要日程中,唯一的想法是:
// 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();
//一个包含O(10^4)Poly3(带6个双精度的结构)的映射
tr1::无序映射SMETEM;
//填充SMETEM
计算时间(SMETEM);
//类型为O(10^3)元素的函数指针的映射
tr1::无序的_-map-diagfunctions=get_-diagram_-map();
这怎么会溢出堆栈
编辑:我试图在valgrind中运行它,这是我得到的错误,google没有提供任何有意义的信息:
valgrind: m_debuginfo/storage.c:417 (vgModuleLocal_addDiCfSI):
Assertion 'cfsi.len < 5000000' failed.
==491== at 0x38029D5C: ??? (in /usr/lib64/valgrind/memcheck-amd64-linux)
valgrind:m_debuginfo/storage.c:417(vgModuleLocal_addDiCfSI):
断言“cfsi.len<5000000”失败。
==491==0x38029D5C时:???(在/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
函数xsection149的汇编程序代码转储(std::tr1::无序映射&,std::vector&,ProcessVars&):
:按%rbp键
:移动%rsp,%rbp
:推送%r15
:推送%r14
:推送%r13
:推送%r12
:按%rbx键
:低于$0xc96b58,%rsp
:mov%rdi,%rbx
:mov%rsi,-0xc8b078(%rbp)//此指令失败
函数的前几行是:
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 +
// .....
}
Poly3 xsectiond149(标准::tr1::无序图和sme,
标准::矢量和ti,
ProcessVars&s)
{
Poly3和(0,0,0,-2);
Poly3前因子,expr;
//CF*CA^2*NF*NA^(-2)
双col0=0.562500000000000000000;
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
增加堆栈大小就达到了目的。感谢大家的帮助!在Valgrind(使用默认工具memcheck)下获取并运行程序。这样,您就可以更轻松地找到故障源
您还可以在Valgrind进入调试器(通常是GDB)的模式下运行Valgrind,然后您可以使用所有酷的GDB命令检查调用者堆栈帧上的值,等等
不管怎样,如果你陷入困境,Valgrind应该帮助你找到一些继续的方向
关于您的编辑,以下是我的回复(引用storage.c的Valgrind源代码r11604):
445/*健全*/
446 VGU断言(cfsi.len>0);
447/*如果失败,则意味着您只有一个过程
448,包含超过500万字节的代码。这很不错
不太可能。不是这样,就是debuginfo阅读器
450.5百万当然是随意的,但它足够大了
451的大小大于
452属于单一程序*/
453 VGU资产(cfsi.len<5000000);
看起来函数xsectiond149
需要一个大约13MB的堆栈帧(请注意指令sub$0xc96b58,%rsp
,并且在两条指令之后尝试在其中写入内容时失败)。您需要确保线程具有足够大的堆栈(默认情况下不会)在调用函数之前
您还可以考虑更改代码生成器,以便在堆上而不是堆栈上分配更多的内容。堆栈溢出或访问冲突?似乎是后者,而不是前者。我想看看引入此segv的签入内容。@GMan:我想这是堆栈溢出,很难说。实际上是访问
smetemp
在调用xsectiond149(…)之前工作正常
,因此我猜将参数传递给函数时会出现问题。看起来像是简单的堆栈溢出。不要在微小的线程堆栈上声明巨大的变量=P@bbtrb,如果你有5兆的源代码要处理,我想这一切都在源代码控制之下。而且你不只是得到5兆的源代码,它肯定是以这样的速度工作的我在过去指出了这一点。那么,它在工作和失败之间发生了什么变化?找到该签入,希望它能更容易地发现问题。:)Th
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 +
// .....
}
445 /* sanity */
446 vg_assert(cfsi.len > 0);
447 /* If this fails, the implication is you have a single procedure
448 with more than 5 million bytes of code. Which is pretty
449 unlikely. Either that, or the debuginfo reader is somehow
450 broken. 5 million is of course arbitrary; but it's big enough
451 to be bigger than the size of any plausible piece of code that
452 would fall within a single procedure. */
453 vg_assert(cfsi.len < 5000000);