【问题标题】:GCC Warns About Function Pointer to Object Pointer CastGCC 警告函数指针指向对象指针转换
【发布时间】:2013-04-08 05:12:21
【问题描述】:

在函数指针和对象指针之间显然是一般意义上的未定义行为,但 POSIX(参见:dlsym)和 WinAPI(参见:GetProcAddress)要求这样做。

鉴于此,并且考虑到此类代码无论如何都针对特定于平台的 API,它对函数指针和对象指针不兼容的平台的可移植性确实无关紧要。

但是 -Wpedantic 无论如何都会发出警告,#pragma GCC diagnostic ignored "-Wpedantic" 没有效果:

warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object [enabled by default]

我想保持启用 -Wpedantic,因为它确实给出了很好的警告,但我不想让真正的警告和错误丢失在关于函数指针到对象指针的不相关警告的海洋中演员表。

有没有办法做到这一点?

在 Windows (MinGW) 上运行 GCC 4.8.0:

gcc (rubenvb-4.8.0) 4.8.0

代码示例

#include <windows.h>
#include <iostream>


int main (void) {

    std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),"five")) << std::endl;

}

发射(使用 -Wpedantic):

warning_demo.cpp: In function 'int main()':
warning_demo.cpp:7:87: warning: ISO C++ forbids casting between pointer-to-funct
ion and pointer-to-object [enabled by default]
  std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),
"five")) << std::endl;

       ^

【问题讨论】:

标签: c++ gcc c++11 mingw gcc-pedantic


【解决方案1】:

我认为你可以在这里使用 g++ 的 system_header 指令:

wrap_GetProcAddress.h:

#ifndef wrap_GetProcAddress_included
#define wrap_GetProcAddress_included

#pragma GCC system_header

template <typename Result>
Result GetProcAddressAs( [normal parameters] )
{
    return reinterpret_cast<Result>(GetProcAddressAs( [normal parameters] ));
}

#endif

【讨论】:

  • #pragma GCC system_header。感谢您让我走上正轨。
【解决方案2】:

这很好用。

template <typename RESULT, typename ...ARGS>
void * make_void_ptr(RESULT (*p)(ARGS...)) {
    static_assert(sizeof(void *) == sizeof(void (*)(void)),
                  "object pointer and function pointer sizes must equal");
    void *q = &p;
    return *static_cast<void **>(q);
}

【讨论】:

    【解决方案3】:

    总有你可以使用的 memcpy 技巧:

    int (*f)() = 0;
    int *o;
    memcpy(&o, &f, sizeof(int*));
    

    你可以在ideone上看到它:m is generating warnings, while g is OK

    至于您可能想要采取的其他行动:一种明显的可能性是“修复”定义dlsym 的标头以实际返回函数指针(如void (*)())。祝你好运。

    【讨论】:

    • 您至少应该 static_assert 函数指针大到足以容纳 void*
    • 那么GetProcAddress 的问题就变成了,如果您想获取您加载的库中不是函数的地址怎么办(请参阅我添加到问题中的代码示例)?
    • @MarkB:鉴于 OP 想要使用 POSIX,实际上是 requires function-pointers to have the same representation as object-pointers,我会认为它是多余的混乱(类似于处理 sizeof(char) 不同于 1)。但是如果你觉得你需要它,你可以添加它(在这种情况下,我宁愿把它放到一个 autoconf 脚本或类似的东西中)。
    猜你喜欢
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    • 2014-01-02
    • 1970-01-01
    相关资源
    最近更新 更多