当我使用WinDDK nmake编译器在'free'(发布版)中构建时,只会发生此错误,后者执行优化。我无法在“已检查”版本中重现此内容或使用VS进行编译。
以下是我的代码中发生的伪代码:
main()
{
//variable init and other code
fprintf(log, "pre nullValue: %lu\n", NULL); //printf added for debugging
otherFunc();
funcWithError(str1, str2, NULL);
fprintf(log, "post nullValue: %lu\n", NULL);
fprintf(log, "post2 nullValue: %lu, %lu, %lu\n", NULL, 0, NULL);
}
BOOL otherFunc()
{
//variable init and other code
callToDll();
//...doing stuff
libusb_usb_open(var1); //If I remove this line there is no problem!!
//...doing more stuff
}
BOOL funcWithError(char* s1, char* s2, FUNC_PTR fp)
{
fprintf(log, "inFunc nullValue: %lu, %lu\n", NULL, fp);
if(fp != NULL)
return FALSE; //This line is being executed erroneously!!
}
日志输出:
pre nullValue:0
inFunc nullValue:0,251208
post nullValue:251208
post2 nullValue:251208,251208,251208
注意:每次运行程序时,重新出现的数字(251208)都是不同的数字
只需更改一行即可修复/导致它。这是libusb usb_open电话。
让我知道其他信息可能会有什么帮助...
答案 0 :(得分:3)
不是完全的灌篮。但是很可能堆栈变得不平衡。在调试器中(是的,您可以调试发布版本),在调用之前和之后检查ESP寄存器的值。应该是一样的。如果函数的调用约定是错误的,则不会。像__stdcall vs __cdecl。
当您使用nmake.exe构建程序时,这可以很好地隐藏自己,很容易忘记在调试版本中打开/ RTC选项,因此会发出堆栈检查代码。 ESP寄存器倾向于在函数返回时恢复自身。直到你构建发布版本,其中函数被内联并且优化了EBP的使用,因此ESP不再自我恢复。
答案 1 :(得分:0)
更新:所以,我终于得到了windbg来打破dll并检查一些事情。正如我最初所怀疑的那样,汉斯指出,由于不匹配的呼叫约定导致堆栈损坏。
仅在发布版本中显示的是编译器优化了0 / Null值以使用ebx寄存器值而不是传递0.在OtherFunc()中,优化使用ebx存储其他几个值,然后是调用Usb_Open()会破坏堆栈,然后当OtherFunc()尝试弹出堆栈以恢复原始的ebx值时,它会恢复垃圾而不是“0”。所以,回到main()中,对NULL的每个优化引用都使用了这个垃圾值。
注意:其他dll调用没有破坏堆栈的原因是因为它们没有参数。
总结答案: