2

这是一个mad-hack,但我试图在执行的特定点故意造成段错误,所以 valgrind 会给我一个堆栈跟踪。

如果有更好的方法可以做到这一点,请告诉我,但我仍然很想知道如何故意造成段错误,以及为什么我的尝试没有奏效。

这是我失败的尝试:

long* ptr = (long *)0xF0000000;
ptr = 10;

我认为 valgrind 至少应该将其视为无效写入,即使它不是分段违规。Valgrind 对此只字未提。

任何想法为什么?

编辑

答案被接受,但我仍然有一些建议,以获得更理智的方式来获取堆栈跟踪......

4

6 回答 6

7

只要打电话abort()。这不是段错误,但它应该生成核心转储。

于 2009-10-20T07:46:34.870 回答
5

很抱歉提到了明显的问题,但为什么不使用带有断点的 gdb 然后使用回溯呢?

(gdb) b somewhere
(gdb) r
(gdb) bt
于 2009-10-20T07:43:04.967 回答
5

你错过了一个*as in*ptr = 10吗?你所拥有的不会编译。

如果确实如此,那当然不会导致段错误,因为您只是分配了一个数字。取消引用可能。

假设在您的操作系统上取消引用 null 会导致段错误,以下应该可以解决问题:

inline void seg_fault(void)
{
    volatile int *p = reinterpret_cast<volatile int*>(0);
    *p = 0x1337D00D;
}
于 2009-10-20T06:37:37.643 回答
3

如其他答案中所述,abort()如果您想完全异常终止程序,或者kill(getpid(), SIGSEGV)必须是分段错误,则可以调用。这将生成一个核心文件,即使您没有在 valgrind 下运行,您也可以将其与 gdb 一起使用以获取堆栈跟踪或调试。

使用 valgrind客户端请求,您还可以让 valgrind 使用您自己的自定义消息转储堆栈跟踪,然后继续执行。当程序不在 valgrind 下运行时,客户端请求什么也不做。

#include <valgrind/valgrind.h>
...
VALGRIND_PRINTF_BACKTRACE("Encountered the foobar problem, x=%d, y=%d\n", x, y);
于 2009-11-01T14:05:34.963 回答
2

你在x86上吗?如果是这样,那么实际上在 CPU 中有一个操作码,意思是“调用任何可能附加的调试器”。这是操作码CC,或更常用的说法int 3。触发它的最简单方法是使用内联汇编:

inline void debugger_halt(void)
{
#ifdef MSVC
   __asm int 3;
#elif defined(GCC)
   asm("int 3");
#else
#pragma error Well, you'll have to figure out how to do inline assembly 
              in your compiler
#endif
}

MSVC 还支持__debugbreak()非托管代码中的硬件中断和托管代码中的 MSIL“中断”。

于 2009-10-20T07:03:57.907 回答
2

将 sig SEGV (11) 发送到进程以强制进行核心转储不是更好吗?

于 2009-10-20T07:10:51.210 回答