DLL内部和外部的函数指针值

时间:2013-12-11 11:13:21

标签: c dll

函数的地址在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共享库模型非常不同(并且没有这个问题。)

3 个答案:

答案 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)