将FILE*传入DLL……

最近还是没有什么好的题目,这篇文章也是炒炒冷饭。

这是大约两年前的事情了,当时我在做一个文件分析系统,要对很多文件类型进行判定,文件类型的判定千差万别,为了保证其灵活性,我打算使用DLL,增加一种新的文件,如果不能简单地根据字节位判断,那就新增一种DLL。

那么是由exe打开文件呢?还是由DLL打开文件呢?我想了一下,从效率和防止代码冗余上考虑,还是由exe打开文件比较好,接下去就简单了,给每个DLL定义统一的接口,将打开的文件的句柄传入,让DLL分析,返回结果,就OK了,但一个同事马上提醒我:“这种方法不可行。”我问为什么?他说以前尝试过,不信试试看。

结果对他不利,因为我的程序一点问题都没有,他想了想说以前DLL传递的不是文件句柄,是文件指针,FILE类型的文件指针,好吧,我也不妨试试看,果然!出现内存错误了。我跟他都很感兴趣,于是研究为什么?你想知道么?哈哈,我看还是让你自己试试看吧,这样印象深刻,我一开始就公布答案太没意思了。

创建一个DLL,随便叫什么,导出个函数,比如:

__declspec(dllexport) JudgeFile(FILE *pFile);

函数里边随便对pFile执行一些操作,比如:

__declspec(dllexport) int JudgeFile (FILE *pFile)
{
 char data[10];
 fread(data, 10, 10, pFile);
 return 0;
}

调用也很简单:

FILE *pf = fopen("123.txt", "r");
if (pf==NULL)
 return -1;
JudgeFile (pf);
fclose(pf);

这样就行了,马上编译运行一下看看,出错了!一个红色的“X”,很亲切吧。

调试发现是DLL里出的错误,也就是那个fread函数,为什么?

因为:DLL有自己独立的代码段和数据段,它使用的库甚至可以跟exe的不一样而不会引起编译时的冲突,如果FILE*是由DLL打开并使用的,那一点问题都没有,那由exe打开就有问题了?是的,因为C库中的fopen其实最后都是对Win API中的CreateFile的调用,但除了这个调用之外,C库还在一个全局数据结构中记录了文件打开的情况及一些相关信息,所以用fopen打开一个文件,光是它返回的FILE*指针还不足以反映文件的全部状况,所有使用到FILE*指针的C库函数,都需要访问那个全局数据结构,问题来了,DLL拥有自己独立的代码段和数据段,那个全局数据结构,DLL访问的是自己的,而不是exe的,这样就出现了偏差,如果全局结构中根本没有要访问的文件的相关信息,硬是就要用这些不匹配的信息尝试操作文件,当然会导致内存出错啦。

那为什么传递一个文件句柄就没有问题?因为CreateFile打开文件返回的是一个内核对象句柄,这个句柄对整个进程来说,理解都是一致的,不存在额外的全局数据结构问题,所以请放心使用。

最后:细节决定成败。任何idea都需要坚固的技术支撑!

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值