元始天尊 发表于 2015-9-25 13:58:34

刚刚的发现-extern误用

一直以来都误用了,来看这种情况:

假设要从ntoskrnl.lib导入IoDriverObjectType
extern "C"
{
POBJECT_TYPE *IoDriverObjectType;
};

这样写可以嘛?
原先以为extern "C"这个extern已经代表了extern本身,然而发现并不是。

如果查看导入表,会发现没有符号,也就是编译器当成全局变量处理
这个例子其实很特殊,如果该符号是个函数的话,那么编译器自然按有无extern分 _imp_和非_imp_处理导入表
然而此时是个变量,外层extern "C"只做符号修饰说明,并不能代表extern 本身!

(引入函数可以用 有extern,和无extern,前者生成_imp_符号的导入表)

也就是说上述语句相当于c文件:
POBJECT_TYPE *IoDriverObjectType;

如果这是个函数,则可以正常引入,而作为变量,编译器会当做本文件声明的变量
所以正确引入方式为:
extern "C"
{
extern POBJECT_TYPE *IoDriverObjectType;
};

分析了有无extern的区别,再来看有无__declspec(dllimport)的区别:
extern "C"
{
__declspec(dllimport) POBJECT_TYPE *IoDriverObjectType;
};
可以发现在引用到改变量处 使用的是*(DWORD*)__imp__IoDriverObjectType
而使用extern的是__imp__IoDriverObjectType

在此抛砖引玉了,如果大家有更多发现请指出

cyycoish 发表于 2015-9-27 19:43:58

赞一个!
页: [1]
查看完整版本: 刚刚的发现-extern误用