2013-01-18 29 views
2

非常简单地说,如果一个C++程序执行以下函数(比如在Windows 7上,使用任何VS版本进行编译),然后崩溃,然后您使用WER附加调试器,或者WER生成崩溃转储并稍后分析崩溃转储。是否可以直接识别覆盖整个堆栈的错误代码?

是从垃圾堆里的信息有可能,以直接推断,这个功能被执行,也就是找到属于那个执行它,这个函数在执行线程痕迹。

或者当我损坏整个堆栈时,所有的执行轨迹都消失了吗?

void bye_bye_stack() { 
    int local = 42; 
    int* stackaddr = &local; 
    while(time(NULL) != NULL) { // prevent optimizations via call to time() 
    ++stackaddr; // stack grows towards smaller addresses, so increasing the pointer will point to info we already put on the stack 
    *stackaddr = local; // destroy stack content 
    // program will (likely) crash here once we reach a read-only page 
    } 
} 
+0

使用valgrind? (填充物) – 2013-01-18 14:12:35

+1

不,这是极端的痛苦。 EIP和EBP是垃圾,ESP指向爆炸的堆栈帧,许多可能已经丢失。你所能做的就是回去尝试找到一个没有踩踏的返回地址。这仍然只给你一小部分调用堆栈。接下来您考虑使用安全的CRT功能。 –

回答

1

一般情况下,通过按照您所做的方式销毁堆栈,您将销毁'callstack',这意味着有关先前调用的例程的信息将会消失。但是,如果您在此例程中触发了访问冲突/分段错误,则将存储发生此事件的指令指针,指向此例程。

但是,如果堆栈损坏,并且您从此例程返回,那么即使不是不可能,也很难找出发生的事情。

如果你想弄清楚发生了什么,我建议使用一个调试工具来找出堆栈被“砸碎”的位置。如果你的意图是破坏执行的证据,确保你从这个例程中'跳'或'返回',而不会触发异常。

+0

问题在于,在此函数内引发了访问冲突*。但是,Windows x86代码将开始尝试查找Win32 SEH异常处理程序,然后这会消除初始错误。通过附加调试器并打破一次机会异常,可以找到该函数。但是,一旦SEH异常处理机制开始执行(即,当不突破第一次机会异常时),似乎所有的痕迹都消失了。 –

1

这不是直接回复你的问题。

但是,当我遇到堆栈被覆盖时,我用来启动在开始覆盖堆栈时立即断言的实用程序gflags。

Gflags is provided by Microsoft

-1

这真的取决于。崩溃转储中提供的后端直接依赖存储在堆栈中的信息。这通常意味着当您怀疑堆栈损坏时,您不能相信回溯。

由您提供的功能很可能会损坏整个堆栈,然后在超出段限制或达到进程不可用的内存时导致异常。此时,堆栈中没有任何东西可以指示嫌疑犯。