使用 -O 优化时 ctypes 返回错误值

Posted

技术标签:

【中文标题】使用 -O 优化时 ctypes 返回错误值【英文标题】:ctypes returns wrong value when -O optimizations used 【发布时间】:2017-05-28 18:05:04 【问题描述】:

具有函数 foo() 的 C++ 代码具有外部名称 dll_foo(),调用时返回值 10。

#include <iostream>

using namespace std;

int foo();

int main()   
    cout << "Start" << endl;  
    return 0;


int foo() 
    return 10;


extern "C" 
    int dll_foo() foo();

这被编译成 .dll 以便以这种方式与 ctypes 一起使用(C++11 出于不相关的原因):

g++ -std=c++11 -O2 -static -shared main.cpp -o main.dll

然后使用 LoadLibrary 在 python 中调用,我也尝试设置 restype 但没有效果:

from ctypes import cdll, c_uint

lib = cdll.LoadLibrary("main.dll")
# lib.dll_foo.restype = c_uint
print(lib.dll_foo())

它每次都会打印一个看似随机的数字(16710260、6224116、...)。如果不使用优化,代码会返回正确的值。

【问题讨论】:

那么returndll_foo() 语句在哪里? 编译器没有打印关于在dll_foo中不返回值的警告? @eryksun 不,它在未优化版本中工作的原因是什么? -Wall编译让g++通知你错误。 @eryksun 是的,我的错误,应该始终使用它开头 【参考方案1】:

我想你的意思是int dll_foo() return foo();。没有它,结果确实是不确定的。

【讨论】:

成功了,谢谢。知道为什么它可以在未优化的编译版本中工作吗? @Lobstw 我想在未优化的版本中foo() 返回标准寄存器rax 中的值,而dll_foo 又不会修改。 @Lobstw:关闭优化后,编译器(可能)调用foo,它会存放其返回值,然后dll_foo() 返回,该值在正确的位置作为返回值。打开优化器后,编译器会检测到您没有(直接)使用foo() 返回的值,因此它完全消除了对foo() 的调用。

以上是关于使用 -O 优化时 ctypes 返回错误值的主要内容,如果未能解决你的问题,请参考以下文章

尝试在 libc 上使用 ctypes 调用 environ 时,为啥 Python 会出现段错误?

如何在没有错误消息的情况下调试 ctypes

使用 ctypes 返回值

ctypes获取扩展模块中函数的返回值

致命错误 C1083:无法打开包含文件:“excpt.h”和“ctype.h”

Python 2 和 3 之间 ctypes 的差异