2011-08-08 27 views
1

我遇到一个问题,那就是在linux下运行的C++程序,用g ++编译后在一段时间后引发一个非法的指令异常,并且我得到一个核心转储。当我使用gdb进行回溯时,我得到使用g ++编译时出现非法指令

(gdb) bt 
#0 0x005e18cf in ATL_dpotrfL() from /usr/lib/liblapack.so.3gf 
#1 0x00000001 in ??() 
#2 0xb786f2e8 in ??() 
Backtrace stopped: previous frame inner to this frame (corrupt stack?) 

我不知道为什么回溯中没有main。 ?? ??似乎是我的Linux库的一部分,它没有调试符号。

我现在的问题是:该程序的问题是什么?图书馆lapack是虚假编译的(我前几天复制过)?或者是否有其他错误?

我做了definitfly没有汇编或类似的东西。只有C++。

感谢 基督教

+0

看起来堆栈被砸碎。在valgrind下运行。 –

+0

好的,那我该怎么做?只是valgrind ./binary?我还没有使用valgrind。我应该启动哪个工具?我认为valgrind用于内存泄漏。 –

+0

是的,从'valgrind。/ binary'开始,看看它说了什么。 –

回答

7

这通常意味着砸了堆栈。特别是值0x00000001,这是非常不可能是一个有效的堆栈地址,所以我会说你溢出堆栈分配缓冲区并覆盖返回地址。

+0

如何获取有问题的代码?有没有一种工具可以给我一个提示?谢谢 –

+0

@Christian:如果你打破了你的堆栈,你怎么能找到栈上当前函数的地址?它坏了。你需要做的就是停止使用原始数组,并开始使用像'boost :: array '这样的安全数组模板,它将通过检查加载来保证安全。 – Puppy

+1

@DeadMG:'boost :: array '保证'reference | const_reference operator []'不会产生任何错误,所以根据定义它不能被检查(可移植的,调试构建是另一回事)。请参阅http://www.boost.org/doc/libs/1_47_0/doc/html/boost/array.html。 –

2

什么DeadMG说,加:

非法指令通常是被编译使用跑步机上没有CPU指令的二进制文件的结果。如果你喜欢编译

g++ -msse4 ... 

,然后英特尔Atom处理器,它不支持SSE4指令集上运行的事情发生这种情况的例子。碰撞不一定发生,例如

int main() {} 

虽然导致生成SSE4指令。当然,对于不可能的代码路径也是如此,这可能不会导致现在的崩溃,但是在将来。

要找到堆栈碎片代码,您可以考虑使用类似cppcheck or similar,Valgrind的LINT,以分而治之的方式调试旧的printf/cout,或使用检查过的STL实现。

2

正如其他人所说,你可能已经拧了你的堆栈。

最常见的原因有:

  • 写在错误的指针(已删除)
  • 写的尖空间之外
  • 宣布在栈上巨大的本地数据

的寻找原因的神奇方法是:

valgrind your_program [args] 

(只需在您通常启动的命令前添加“valgrind”)。安装valgrind(如果还没有在这里)必须在发行版上有一个包,因为它是一个广泛使用的工具。)

然后valgrind会检查你的程序在运行时(放慢一点)并立即报告你作为写入发生在不应该的地方(例如,在堆栈上)