与例如:
如何在VC++中毒化标识符?
在C++中"毒化一个函数"是什么意思?
有没有办法"正确"毒化一些声明(或实现)不受我控制的函数?
具体来说,我试图阻止某些Windows API函数的使用可能导致意外结果,例如CreateFileA(使用T宏隐藏了混合ANSI和Unicode的事实)或SetWindowLong(这将导致您的程序无声地失败,没有错误,也没有机会知道64位系统出了什么问题).
我对"正确"中毒的定义是,试图调用该函数会破坏构建时出现可读错误(如果错误发生在源代码中的正确位置,则奖励积分).
优选地,这应该是便携式的,并且至少它必须与GCC和clang一起工作.
到目前为止我尝试/看过的内容:
最简单,最明显的解决方案是利用预处理器:
#define CreateFileA __poison_ANSI_CreateFileA
Run Code Online (Sandbox Code Playgroud)
这对于一个特定的函数以及其他几个函数非常有效,完全按照预期工作,具有提示问题的精确错误并指向源中的正确位置:
error: no matching function for call to '__poison_ANSI_CreateFileA'
note: expanded from macro 'CreateFile'
note: expanded from ... (precise location in source)
Run Code Online (Sandbox Code Playgroud)
对于不同的功能,每个人都需要有一个唯一的名称,以避免冲突的定义错误,这是繁琐但容易完成的.到目前为止一切都那么好,除了它不适用于MinGW-w64标头本身使用可变参数宏篡改名称的函数,例如CreateWindow或SetWindowLong.无论如何,这些编译得很好,中毒与否.
#pragma GCC poison铿锵碰巧也理解了(并且还有自己的版本),外观和声音应该完全符合我的要求,并以最惯用的方式.唉,它不起作用.或者说,它运作得太好了.
当中毒名称出现在声明中时,使用pragma指令中毒的函数已经触发错误,这意味着... 每次都在包含标题的每个构建中.这对编写程序没有多大帮助!
这些都有一个巨大的缺点,你必须完全复制类型定义,以免在合法的调用上出现"模糊函数调用"错误.另一方面,它们不起作用.clang抱怨__attribute__((__error__))但忽略gnu::__error__或gnu::error同样gnu::deprecated.此外,标准[[deprecated]]都很好,但似乎没有什么(编译好,甚至没有警告?!).
有什么我能做的吗?
我会将预处理器黑客作为第一道防线,因为它似乎可以很好地捕获某些情况,为您提供源代码中的确切位置。
我还会设置第二层防御,确保您提供一个目标文件,其中包含您想要中毒的函数的变体,例如:
HWND WINAPI CreateWindowEx(DWORD dwExStyle, LPCTSTR lpClassName,
LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth,
int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
LPVOID lpParam)
{
std::cerr << "Attempting to use poisoned function CreateWindowEx\n";
exit(1);
}
Run Code Online (Sandbox Code Playgroud)
如果您将其链接为目标文件(不是库,因为库只会链接到未解析的引用),则会出现三种可能的情况(一旦它通过了标头中毒):
就这样做而言,单个poisoned.h和poisoned.c应该可以解决问题,您只需确保将您想要中毒的所有功能都添加到两者中即可。
现在我还没有测试过这个方法是否适用于 MinGW,但值得一试,因为在最低级别,它需要在某个时刻调用真正的Windows 函数。
我可以预见您的 MinGW 问题发生的唯一方法是它调用一些已编译的 MinGW 对象,这些对象最终调用 Windows 函数。如果发生这种情况,那么链接器捕获也应该捕获它。
| 归档时间: |
|
| 查看次数: |
262 次 |
| 最近记录: |