函数的地址在DLL内部和外部具有不同的值。
稍微简化一下,我在dll中有以下代码
typedef struct Holder Holder; /* Struct */
typedef int (*pfn_t)(Holder*); /* Function pointer */
struct Holder { pfn_t pfn; }
int IsSame( Holder *h ){ return h->pfn == IsSame; }
在主程序中,我有:
Holder h = { IsSame };
assert( IsSame(&h) );
断言开火了!问题是h.pfn设置为main.exe中跳转表的地址,而DLL中的代码将其与DLL中函数的地址进行比较。
我是否可以使用任何魔术注释或链接器选项来说服断言不发射?
请注意,这是在Windows上。 Posix共享库模型非常不同(并且没有这个问题。)
答案 0 :(得分:2)
你的问题可能是由此造成的:
函数调用通过额外的JMP指令。所以它是相对地址
相反如果您将使用LoadLibrary() GetProcAddress()
,它将检索dll函数的地址。
答案 1 :(得分:1)
我认为这就是答案:
http://mingw.5.n7.nabble.com/Direct-dll-linking-and-comparing-function-pointers-td2875.html#a2876
当我在主程序中声明__declspec(dllimport)
时,我需要使用IsSame
,当我在DLL中定义IsSame时,我需要__declspec(dllexport)
才能使函数指针相等。
答案 2 :(得分:0)
如果你想进行这种功能比较,你应该使用GetProcAddress或导出你的DLL中的接口来初始化任何DLL函数指针,以确保你比较的地址是模块所看到的函数地址驻留在而不是从.exe到DLL的蹦床,这是Windows loader magic(TM)的所有部分。
动态链接依赖于使用trampolines,然后跳转到“导出地址表”中填充的条目。与标识符导入的函数的比较仅在其链接的模块中有效。因此,代码背后的假设是错误的,因为它们假定.exe中的地址是函数的地址。如果你想要一个常量的地址,你需要以与该模块中的任何数据相同的方式显式地导出它,并隐式地将其导入任何其他模块(即GetProcAddress)