wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
阅读:2237回复:16

win32动态连接库错误!!!

楼主#
更多 发布于:2004-06-02 14:29
我在win32动态连接库中写了一个函数,功能是打开驱动程序的句柄,
动态库,和应用程序编译都是正确的。
   然后,在一个对话框程序中调用这个动态连接库中的这个函数可时出现了如下的错误,说某个内存地址不能够为写,请问高手们这应该如何解决阿?
walkonthesky
驱动中牛
驱动中牛
  • 注册日期2003-11-26
  • 最后登录2012-11-06
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2004-06-02 16:14
缓冲区溢出错误
编译时不会发现错误

运行时只有触发了特定的条件才可能触发错误

检查你的程序,对数组/指针类变量的使用做检查。特别注意边界的检查。比如,你定义了char buff[10],却在程序里向里面写了100个Byte,如果这多出来的90个CHAR没有写到系统使用的内存(.text,.code)之类的地方,那么不会有什么问题,或者说问题被隐藏了,但是一旦发生以上的情况,就会导致你说的那种情况。
[img]http://www.driverdevelop.com/forum/upload/walkonthesky/2004-07-08_2004-07-07_b847.gif[/img]
walkonthesky
驱动中牛
驱动中牛
  • 注册日期2003-11-26
  • 最后登录2012-11-06
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-06-02 16:17
最好有代码出来
[img]http://www.driverdevelop.com/forum/upload/walkonthesky/2004-07-08_2004-07-07_b847.gif[/img]
snowStart
驱动老牛
驱动老牛
  • 注册日期2004-04-06
  • 最后登录2011-06-02
  • 粉丝0
  • 关注0
  • 积分95分
  • 威望19点
  • 贡献值177点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-06-02 17:30
就是楼上说的原因,
你可以在该对话框中点击取消,进入调试程序状态,以便定位具体哪一行,哪个语句,哪个函数出错
学习,关注,交流中... [email=fengyu@163.com]Email:snowstarth@163.com[/email] [url]http://bbs.zndev.com/?a=snowStart[/url]
wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2004-06-02 19:46
在程序中我就没有定义指针,更没有使用数组,只有调用了createfile()函数打开驱动程序的句柄,他就会
报上面的错误
wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-06-02 20:16
点击取消按钮,出现的是汇编代码的嘛,
那个怎么和知道源程错在那行?能指点一下么?
wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-06-02 20:31
我的DLL和对话框程序编译时都没有错误,和警告
Test3()是我在动态连接库中定义的,OnButton2()是对话框程序中定义的,
用来调用Tes3()的。
void CTestDlg::OnButton2()
{
Test3();
}

DLL的引出头文件LINK.H是这样定义的:


#ifdef MYLIBAPI
#else
#define MYLIBAPI extern \"C\" __declspec(dllimport)
#endif


MYLIBAPI BOOL LoadDSPFile(char* pFileName);
MYLIBAPI BOOL Test3();

LINK.CPP是这样定义的:

#include \"windows.h\"
#define MYLIBAPI extern \"C\" __declspec(dllexport)
#include \"Link.h\"

BOOL OpenDevice();
MYLIBAPI BOOL LoadDSPFile(char* pFileName)
{
if(OpenDevice())
MessageBox(NULL,\"ok\",\"\",MB_OK);
else
MessageBox(NULL,\"Fail\",\"\",MB_OK);
return true;
}

MYLIBAPI BOOL Test3()
{
OpenDevice();
return true;
}

OpenDevice() 函数在DLL中是这样定义的:
(这个其实是DriverStudio 自动生成(OpenByIntf.cpp)的我没有做过任何的改动)


#include <stdlib.h>
#include <windows.h>
#include <winioctl.h>
#include <devintf.h> // DriverWorks

// OpenByInterface
//
// Opens the nth device found with the given interface class

HANDLE OpenByInterface(
GUID* pClassGuid, // points to the GUID that identifies the interface class
DWORD instance, // specifies which instance of the enumerated devices to open
PDWORD pError // address of variable to receive error status
)
{
HANDLE hDev;
CDeviceInterfaceClass DevClass(pClassGuid, pError);

if (*pError != ERROR_SUCCESS)
return INVALID_HANDLE_VALUE;

CDeviceInterface DevInterface(&DevClass, instance, pError);

if (*pError != ERROR_SUCCESS)
return INVALID_HANDLE_VALUE;

hDev = CreateFile(
DevInterface.DevicePath(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);

if (hDev == INVALID_HANDLE_VALUE)
*pError = GetLastError();

return hDev;
}




附件名称/大小 下载次数 最后更新
2004-06-02_源代码.rar (2699KB)  3
wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2004-06-02 20:34
各位高手们,我实在是很着急要解决这个问题,请你们帮助我一下好么?
先道声谢了!
walkonthesky
驱动中牛
驱动中牛
  • 注册日期2003-11-26
  • 最后登录2012-11-06
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2004-06-03 09:55
我不用DriverStudio,没有办法调试
说有个文件找不到,<devintf.h>
[img]http://www.driverdevelop.com/forum/upload/walkonthesky/2004-07-08_2004-07-07_b847.gif[/img]
walkonthesky
驱动中牛
驱动中牛
  • 注册日期2003-11-26
  • 最后登录2012-11-06
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2004-06-03 10:08
但是你的代码组织我实在看不懂
斗胆提个人看法。

所有的DLL都有DLLMAIN,你的DLLMAIN在什么地方

程序调用的时候如何加载你的DLL,完成以后又如何卸载你的DLL,多个程序引用你的DLL,引用记数怎么处理。

Every DLL must have an entry point, just as an application does. The system calls the entry-point function whenever processes and threads load or unload the DLL. If you are linking your DLL with a library, such as the C run-time library, it may provide an entry-point function for you, and allow you to provide a separate initialization function. Check the documentation for your runtime library for more information

应该说你的程序本身编制就是有问题的,代码不全。
建议不用以现有的代码为基础调试,重新写代码,至少把代码补充完整以后再调试。
[img]http://www.driverdevelop.com/forum/upload/walkonthesky/2004-07-08_2004-07-07_b847.gif[/img]
walkonthesky
驱动中牛
驱动中牛
  • 注册日期2003-11-26
  • 最后登录2012-11-06
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2004-06-03 10:10
你的问题我也找到了

原因在于不知道如何加载你的DLL,因为找不到DLL入口,所以只能乱引用指针,导致出现你发现的问题。
[img]http://www.driverdevelop.com/forum/upload/walkonthesky/2004-07-08_2004-07-07_b847.gif[/img]
wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2004-06-03 12:29
昨天晚上,熬到深夜3:00钟终于把问题找到了。我非常感谢各位的关和回复,谢谢各位。
wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2004-06-03 13:47
感谢你们的帮助walkonthesky,snowStart我已经把分数都给你们了。还有所有回复过我帖子的朋友我都给了分了!谢谢。原来,把自己遇到的问题贴出来,是这么的有帮助,希望能够有机会和大家多交流。
我的联系方式:
wei_ziyong@163.com
QQ:44176254

为了感谢大家对我的帮助我把我的问题的错误发表出来:

HANDLE OpenByInterface(
GUID* pClassGuid, // points to the GUID that identifies the interface class
DWORD instance, // specifies which instance of the enumerated devices to open
PDWORD pError )
其实,错误的原因是上面的这个OpenByInterface()函数的第三个参数
引起的。因为第三个参数是个指针PDWORD类型,所以当调我们用这个函数时,传递的给他的第三个参数都是这样定义的(当然这只是一般的常用的方式中的一种):
Test()
{
   PDWORD pErr;
   OpenByInterface(,,pErr);
}
当然,也可以这样调用:
Test()
{
   PDWORD pErr=ERROR_SUCCESS;
   OpenByInterface(,,pErr);
}
在这里,如果是采用上面的任何的一种方式,给那个函数传递第三个参数肯定是要出现上面我遇到的错误;但是如果是采用下面的这种方式给函数传递第三个参数(而且也是唯一的能够正确的调用这个函数的方式,基本上别无他法,当然除了引用哈):
Test()
{
   DWORD Err=ERROR_SUCCESS;
   OpenByInterface(,,Err);
}
这样调用就是正确的。原因是这样的:
这要看这个函数的内部代码是怎样的使用这个参数的。
HANDLE OpenByInterface(
GUID* pClassGuid, // points to the GUID that identifies the interface class
DWORD instance, // specifies which instance of the enumerated devices to open
PDWORD pError // address of variable to receive error status
)
{
HANDLE hDev;
CDeviceInterfaceClass DevClass(pClassGuid, pError);

if (*pError != ERROR_SUCCESS)
return INVALID_HANDLE_VALUE;
......................

看到这一段了吗,有个*pError方式的调用,直接去访问pError这个地址
的这个地址。如果传递给他的参数是这样定义的话:PDWORD pError;
他就回把pError的值作为内存地址去访问,比如把pError=ERROR_SUCCESS;而ERROR_SUCCESS的直在WINDOWS里是0,这样当程序运行到if (*pError != ERROR_SUCCESS)这里时,就去访问内存地址为0x00000000的单元,这样出现我遇到的错误了。而使用这方式
DWORD Err=ERROR_SUCCESS;
   OpenByInterface(,,Err);
调用,程序执行到
if (*pError != ERROR_SUCCESS)
    return INVALID_HANDLE_VALUE;
这里就不是对地址为0x00000000的地址空间进行访问了。
而只是对Err变量的地址空间进行访问了,而变量的地址空间是系统分配的是合法的地址。
说到这里大家都应该清楚了把,这就是这个错误的真正的原因。
    不过,我还是又有了一个新的疑问,为什么把参数定义为指针PDWORD类型传递是合符语法的规则的啊,怎么会导致上面的哪个错误啊,与自己使用指针的想法恰恰相反了?写到这里我突然明白了这只是指针如何进行初使话的问题。终于彻底想通了。

上面的情况大家可以用我的代码实验。旧可以 看出结果了。再次,感谢大家赐予的灵感!!














wei_ziyong
驱动牛犊
驱动牛犊
  • 注册日期2003-12-31
  • 最后登录2010-04-30
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望16点
  • 贡献值0点
  • 好评度16点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2004-06-03 14:06
walkonthesky
再次问你一下,我的DLL是正确的啊,没有DLLMAIN()他照洋能够安全的的运行啊,我以今使用过多次了。如果要加载他的话,可以不须要主函数吧。除了缺少dllmai()函数,我的代码哪个地方比较的混乱啊,请你多指教!能给一个示范性的dll的筐架的原代码么?比如,有dllmain()、
引用计数怎么解决的、加载DLL,完成以后又如何卸载你的DLL等。谢谢落!?
walkonthesky
驱动中牛
驱动中牛
  • 注册日期2003-11-26
  • 最后登录2012-11-06
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2004-06-04 08:47
我上面的那一段是MSDN的说法
我也一直写DLLMAIN的

我不知道为什么你没有DLLMAIN也可以使用
BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID lpReserved

                                    )

{

    switch (ul_reason_for_call)

       {

              case DLL_PROCESS_ATTACH:

              case DLL_THREAD_ATTACH:

              case DLL_THREAD_DETACH:

              case DLL_PROCESS_DETACH:

                     break;

    }

       hInstance=(HINSTANCE)hModule;          //得到DLL实例

    return TRUE;

}

以上是一个DLLMAIN的入口函数
任何一个DLL都有可能被多个AP引用
所以必须规范的处理
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:

至少处理引用计数
在计数器为0的时候将该DLL从内存中卸载
否则,该DLL将不能卸载
[img]http://www.driverdevelop.com/forum/upload/walkonthesky/2004-07-08_2004-07-07_b847.gif[/img]
walkonthesky
驱动中牛
驱动中牛
  • 注册日期2003-11-26
  • 最后登录2012-11-06
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望20点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2004-06-04 08:52
乱是一种感觉
最好将。CPP的函数原型使用同名的。H文件导出,然后再包含,而不要在。CPP里直接写函数原型。只有函数实现在本文件,而且 该函数被前面的函数引用的时候才需要象你那样处理为前置申明。

看你的代码感觉完全是另外一套规则,通用的规则全部失效,感觉很累。
[img]http://www.driverdevelop.com/forum/upload/walkonthesky/2004-07-08_2004-07-07_b847.gif[/img]
diamond030
驱动牛犊
驱动牛犊
  • 注册日期2004-11-02
  • 最后登录2004-11-14
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2004-11-14 21:39
没有写dllmain(),
系统会从其它dll中调用一个默认的dllmain()来运行,
忘了是哪里提到过的  :)
另外,有人知道为什么lcc中的dll入口函数为libmain(),怎么
跟静态库一样呢???
 :)
游客

返回顶部