写了一个模块(dll),里面的数据结构主要是链表。
另外写了一个测试程序,
void CInference_testDlg::Onengin()
{
//用来得到调用dll函数的返回结果的
struct result *p;
UpdateData(true);
m_text.TrimLeft();
char element[100]="";
m_filename.Format("%s","rule.dat");
p = engine(&m_filename,&m_text,1); //call function of dll
AfxMessageBox(p->message);
}void CInference_testDlg::OnExit()
{
OnOK();
}
其实是传递几个参数后调用dll模块。可是每次按退出按钮的时候会报错: "0x10212923"指令引用的“0x01422750”内存。该内存不能read调试的时候发现如果调用dll函数执行后就会报错,如果不执行就不会报错了。所以我想
错误应该是由于dll函数造成的。但是每次执行dll函数的时候运行都很正常——我指运
行过程中各数据和返回的结果都正确。而且AfxMessageBox(p->message);也都能正常执行。既然如此,我执行函数调用后OnBegin()函数已经执行完了——这个消息被处理完成了,这个时候我在按退出按钮,又怎么会突然冒出来Access Violation问题啊?!如果
真的是我在dll文件里面有wild pointer的话,也不会OnBegin()函数正常执行完啊,而应该是在结果被显示之前就报错了啊!
请高手指点迷津!
另外写了一个测试程序,
void CInference_testDlg::Onengin()
{
//用来得到调用dll函数的返回结果的
struct result *p;
UpdateData(true);
m_text.TrimLeft();
char element[100]="";
m_filename.Format("%s","rule.dat");
p = engine(&m_filename,&m_text,1); //call function of dll
AfxMessageBox(p->message);
}void CInference_testDlg::OnExit()
{
OnOK();
}
其实是传递几个参数后调用dll模块。可是每次按退出按钮的时候会报错: "0x10212923"指令引用的“0x01422750”内存。该内存不能read调试的时候发现如果调用dll函数执行后就会报错,如果不执行就不会报错了。所以我想
错误应该是由于dll函数造成的。但是每次执行dll函数的时候运行都很正常——我指运
行过程中各数据和返回的结果都正确。而且AfxMessageBox(p->message);也都能正常执行。既然如此,我执行函数调用后OnBegin()函数已经执行完了——这个消息被处理完成了,这个时候我在按退出按钮,又怎么会突然冒出来Access Violation问题啊?!如果
真的是我在dll文件里面有wild pointer的话,也不会OnBegin()函数正常执行完啊,而应该是在结果被显示之前就报错了啊!
请高手指点迷津!
2.可能你在别处调Freelibrary()
我的测试程序我只写了上面两个函数,执行完Onbegin()函数后我就退出,然后报错。
我调用dll模块函数的方法不是运行时载入的方法,所以没有使用LoadLibraryEx(),也就没有使用
FreeLibrary()了。
显示 Please enter the path for DBGHEAP.C.
然后然我选择目录,但是机子上面没有这个文件阿。
然后我选择cancel候,就指到一条汇编代码了
--- No source file --------------------------------------------------------------------------------------------------------
102128FC int 3
102128FD int 3
102128FE int 3
102128FF int 3
--- dbgheap.c -------------------------------------------------------------------------------------------------------------
CheckBytes:
10212900 push ebp
10212901 mov ebp,esp
10212903 push ecx
10212904 push ebx
10212905 push esi
10212906 push edi
10212907 mov dword ptr [bOkay],1
1021290E mov eax,dword ptr [nSize]
10212911 mov ecx,dword ptr [nSize]
10212914 sub ecx,1
10212917 mov dword ptr [nSize],ecx
1021291A test eax,eax
1021291C je CheckBytes+7Eh (1021297e)
1021291E mov edx,dword ptr [pb]
10212921 xor eax,eax10212923 mov al,byte ptr [edx] //这便是指向的汇编语句10212925 mov ecx,dword ptr [bCheck]
10212928 and ecx,0FFh
1021292E mov edx,dword ptr [pb]
10212931 add edx,1
10212934 mov dword ptr [pb],edx
10212937 cmp eax,ecx
10212939 je CheckBytes+7Ch (1021297c)
1021293B mov eax,dword ptr [bCheck] 看这条汇编语句应该是wild pointer问题,可是如果是调用dll函数的时候出现这种情况的话就应该是在执行函数的时候就报错了,现在却是执行完要退出的时候出问题。
我不太清楚dll函数调用后程序退出的时候(我调用dll函数采用的不是动态加载的方式)编译器会怎么处理,它应该有一个类似于析构的过程吧,如果这样的话可能是这块地方出错了。请高手指点。
m_filename和m_text是什么类型的?CString?如果是,那么可能是不安全的。
engine是如何定义的?
engine(const CString& filename, const CString& text, int nResaved = 0);?
反正我觉得这样是不安全的,我不太清楚CString的引用、拷贝构造等是怎么实现的,看他的源代码好像是通过引用计数实现的。我做过一个程序,也是主程序调用dll并传递CString类型变量,无论怎么传递都出错,但别的类型(int,float等)不会出错(最后是通过先将参数写入注册表然后再在dll中读注册表实现参数传递的。也有可能通过共享数据段实现,但我没试过,不知道行不行)。而当主程序(客户端)用:
CString str = _T("124");
mydllinterface(str.GetBuffer(10));调用dll;
dll(服务器端)用纯C++的string接受参数:
int mydllinterface(string str);
则不会出错。
用int mydllinterface(char* szp);
也不会错;
不知以上是否对你有帮助。
#define DllExport _declspec(dllexport)
extern "C" DllExport struct result * engine(CString *,CString *,int); 对于CString的不安全我也深有同感,在写程序的过程中我就有一次因为使用了CString::Empty()函数导致其他与之很不相干的数据被破坏了,后来改用其它的方法
完成才了结。 不过我的数据传递到正常,程序运行也能正常——我做的是推理机,可以得到正确的推理结果。
就是退出程序的时候会报错。——所以很迷惑。
返回的p是在dll里面分配的内存吧?那它的释放也应该通过调用dll,
否则,可能两边使用不同的内存管理模式,出错,详见windows核心编程。
AFX_MANAGE_STATE(AfxGetStaticModuleState());
keios(嘿嘿) 朋友说得很有道理,我去查看了 《windows核心编程》,里面说到两边使用不同的内存管理模式而出错的问题,我感觉我的程序就可能是犯了这个错误。
p = engine(&m_filename,&m_text,1); //call function of dll
返回的p是指向dll内存的一个链表的指针,如果错误是因为程序退出的时候尝试释放
p所指向的内存而出错的话,我在程序结束前把p指向NULL.不过还是出错了。不知道为什么?
看你的代码,肯定不是因为释放p的问题,你的程序根本没有释放,也就是说内存泄漏,但不会造成你所说的错误,如果你愿意,我可以帮你找,但你要把代码发到我邮箱里[email protected]
你可以把机密的部分给删掉
到dll函数模块中仔细搜寻一下。
不过很纳闷的是为什么这种问题报错不是在调用dll函数模块的时候报错,却在调用程序结束的时候
报错。
再次感谢各位朋友的关心。