1

场景是这样的。我看到一个结构在按值传递到回调函数时被损坏,从 C API 到 C++ 一个(通过静态方法)。

库 A:基于 C 的 API,通过 gcc 构建 库 B:基于 C++ 的 API,通过 g++ 构建

库 A 构建为带有 -fPIC 的静态库。库 B 构建为共享库,链接库 A,也使用 -fPIC 构建。

在库 A 中定义的是一个结构:

typedef struct doomed_struct
{
    uint32_t field1;
    uint32_t field2;
    CHILD_STRUCT1 field3;
    CHILD_STRUCT2 field3;
} DOOMED_STRUCT;

和一个回调函数:

typedef void (_CALLBACK_FUNC *FUNCTION)(uint32_t arg1, uint8_t arg2,
    uint8_t arg3, DOOMED_STRUCT arg4);

C++ API 在类中定义了一个静态方法,并将其交给 C API 进行回调。当这个回调被调用时,简单的类型化 arg1,2,3 可以很好地完成它,但是结构中的字段是垃圾,并且每次执行都会改变。

我也尝试将 C++ API 的函数更改为extern "C"静态函数,但没有运气。

如果我在 C API 中存根一个 C 函数并调用它只是为了测试,那么该结构将被很好地复制而不会损坏。

令人沮丧的部分?这一切都适用于 Linux 和 QNX 上的 MSVC8/9/10、gcc 4.4.x(32 和 64 位)。几年后回到 gcc 4.1,这会弹出。

如果我更改回调函数以通过指针而不是副本传递结构,它工作正常!唉,C API 有 ABI 限制,不能修改。

它闻起来像是某种调用约定或结构布局问题,但我不知道要为这样的事情转动什么旋钮。总体而言,该结构为 16 个字节,因此它不会对我产生堆栈问题。

4

1 回答 1

1

这似乎与优化级别有关。代码正在使用 -O0 构建并且失败,现在使用 -O1 它可以工作。没有兴趣深入挖掘!

于 2012-08-24T19:30:45.827 回答