指针函数参数损坏,堆栈损坏?

Posted

技术标签:

【中文标题】指针函数参数损坏,堆栈损坏?【英文标题】:Pointer function argument corrupted, Stack corruption? 【发布时间】:2016-05-07 01:25:05 【问题描述】:

我正在构建一个由 py​​thon 通过 ctypes 调用的 C++ 库。该函数有一个指向结构的指针作为参数,并将其传递给其他(内部)函数。它看起来像这样:

extern "C" __declspec(dllexport) void USBEndpoint_subscribe(USBEndpoint* endpoint, CALLBACK callback) 
  try 
    subscribe_internal(endpoint, callback);
   catch (int e_code) 
    exception_report(__FILE__, __LINE__, e_code); \
   catch (...) 
    exception_report(__FILE__, __LINE__);


void subscribe_internal(USBEndpoint* endpoint, CALLBACK callback)

  ...

问题是在 USBEndpoint_subscribe 收到的端点值与进入 subscribe_internal 的值不同。例如:

在调试时,我可以看到 USBEndpoint_subscribe 收到: 端点=0x00000000088f0680(和回调=0x0000000000540f50)

一旦我进入 subscribe_internal,在 subscribe_internal 中的值是: 端点=0x000007fef15f7740(和回调=0x0000000000000000)。

我没有产生其他线程,我正在以发布模式编译库**。我唯一的嫌疑人可能是堆栈损坏,但实际上我知道发生了什么。

非常欢迎任何关于可能发生的事情的提示。

** 我已经在调试模式下编译了 python,但是设置蜘蛛很慢,如果我使用调试编译的版本,我会失去交互式控制台,所以我更喜欢使用发布 python 并在发布中编译我的库。

编辑:

按照建议,我使用调试版本的 python 和库的调试编译。但我仍然得到相同的行为(端点:0x0000000002be80e0->0x0000000000000000,回调:0x0000000000320f88->0x00000000024d24b8)。此处未显示其他有用信息,但未处于发布模式。

【问题讨论】:

在 Windows 上假设这是 x86-64 是否安全? 这可能不方便,但您可能应该分解并使用调试版本。发布版本典型地去除所有调试符号并执行可能导致调试器显示一些意外结果的优化。 是的,这是 Windows 上的 x64。 我认为您应该尝试在汇编模式下单步执行,看看正在执行哪些指令。这两个参数的类型实际上都是USBEndpoint*,还是为了说明而简化了?如果其中一个实际上是另一个的基类,则可能需要调整指针。 @MartinBonner 在汇编模式下调试我可以看到调用约定不正确。谢谢! 【参考方案1】:

我正在使用 CDLL("path") 加载库,这使得调用约定为 cdecl。即使我在 VS2008 中使用 /Gd 进行编译,它似乎也在使用其他约定。将 __cdecl 附加到函数声明即可解决问题。

【讨论】:

__cdecl 应该是 x86 目标的默认值。对于 x64,__cdecl__stdcall 将被忽略;除非指定 __vectorcall,否则编译器使用 Windows x64 调用约定。

以上是关于指针函数参数损坏,堆栈损坏?的主要内容,如果未能解决你的问题,请参考以下文章

堆栈缓冲区溢出会导致堆损坏吗?

数组变量周围的堆栈损坏

进程内存和内存损坏

基本线程导致 malloc():内存损坏:[关闭]

P/Invoke:内存损坏与指针

作业帮助,分段错误,双重释放或损坏,free():无效指针