我用c写了一个dll,有个方法接受FILE*参数,然后在方法里分析file的内容,最后返回结果另外,用c写了一个主程序,该主程序通过fopen打开一个文件,调用DLL中的方法,出错(在主程序中可以对该FILE*正常使用)用/MTd参数时,跟踪进去发现是在_lock_str(stream)出访问冲突//////fread.c中的相关代码
#ifdef _MT
/* define locking/unlocking version */
size_t __cdecl fread (
void *buffer,
size_t size,
size_t count,
FILE *stream
)
{
size_t retval; _lock_str(stream); /* lock stream */
__try {
/* do the read */
retval = _fread_lk(buffer, size, count, stream);
}
__finally {
_unlock_str(stream); /* unlock stream */
} return retval;
}
#endif /* _MT */用/MLd参数时,跟踪进去发现是在校验文件句柄时出错
////read.c中的相关代码
/* now define normal version */
int __cdecl _read (
int fh,
void *buf,
unsigned cnt
)
{
int bytes_read; /* number of bytes read */
char *buffer; /* buffer to read to */
int os_read; /* bytes read on OS call */
char *p, *q; /* pointers into buffer */
char peekchr; /* peek-ahead character */
ULONG filepos; /* file position after seek */
ULONG dosretval; /* o.s. return value */ /* validate fh */
if ( ((unsigned)fh >= (unsigned)_nhandle) ||
!(_osfile(fh) & FOPEN) )
{
/* bad file handle */
errno = EBADF;
_doserrno = 0; /* not o.s. error */
return -1;
}环境vs.net,win 2k server
#ifdef _MT
/* define locking/unlocking version */
size_t __cdecl fread (
void *buffer,
size_t size,
size_t count,
FILE *stream
)
{
size_t retval; _lock_str(stream); /* lock stream */
__try {
/* do the read */
retval = _fread_lk(buffer, size, count, stream);
}
__finally {
_unlock_str(stream); /* unlock stream */
} return retval;
}
#endif /* _MT */用/MLd参数时,跟踪进去发现是在校验文件句柄时出错
////read.c中的相关代码
/* now define normal version */
int __cdecl _read (
int fh,
void *buf,
unsigned cnt
)
{
int bytes_read; /* number of bytes read */
char *buffer; /* buffer to read to */
int os_read; /* bytes read on OS call */
char *p, *q; /* pointers into buffer */
char peekchr; /* peek-ahead character */
ULONG filepos; /* file position after seek */
ULONG dosretval; /* o.s. return value */ /* validate fh */
if ( ((unsigned)fh >= (unsigned)_nhandle) ||
!(_osfile(fh) & FOPEN) )
{
/* bad file handle */
errno = EBADF;
_doserrno = 0; /* not o.s. error */
return -1;
}环境vs.net,win 2k server
你说的我考虑过,DLL是用LoadLibrary()加载(只能用这种办法,因为可能使用的DLL是不确定的,但接口一样),我不清楚这样加载后DLL与exe是不是在同一地址空间(应该是吧?),如果不是,则如何解决,请教。◆maoxianwang(大大㊣BETAⅡ我想赶快结婚那样就可以)
extern "C"加了,依然不对◆Kevin_qing():
DLL与exe都是使用的相同的线程库,我手动改过,这一点我可以保证,但还是不对我还怀疑是不是系统环境的问题,因为环境是win 2k,安装了.Net,打了sp3,我怀疑是因为装了.Net的缘故,没有别的环境,没法试验,唉...
我上次头昏,连问题都没看清楚就胡说了一把。
这次我要好好看看,争取将功补过。
exe程序:
main(){
char *dllFilePath = getDLL();
HINSTANCE hDLL = LoadLibrary(dllFilePath); //得到接口函数地址
typedef SomeStruct* (*InfoGetter)();
InfoGetter getInfo = getFunAddress(hDLL); //根据字符串得到特定函数的地址
typedef Result* (*FileReader)(FILE*);
FileReader readFile = (FileReader)getFunAddr(getInfo(),"readFile"); typedef int (*FileWriter)(FILE*,char*);
FileWriter writeFile = (FileWriter)getFunAddr(getInfo(),"writeFile");
//准备文件
char *filePath = getFilePath();
FILE *pf = fopen(filePath,"r"); //调用
Result r = readFile(pf); //<------此处调用的是DLL中的函数,执行时出现非法操作 //或者调用
char *filePath2 = getFilePath();
FILE *pf2 = fopen(filePath2,"w");
if(writeFile(pf2,"some text")//<---调用DLL中函数,成功执行并返回
{
fclose(pf);//<----此时失败,出非法操作
}
}DLL文件:__declspec(dllexport) SomeStruct* info(){
return void* []{readFile,writeFile};
}__declspec(dllexport) Result* readFile(FILE* file){
//...
fread(buf,1,sizeof(buf),file);//<---读不出任何东西
//...
return result;
}__declspec(dllexport) int writeFile(FILE* file,char* text){
return fprintf(file,"%s",text);
}希望能描述清楚
但我是在文件关闭删除文件句柄出问题,你能详细描述出错提示吗?
可发到我的邮箱中[email protected]
....
HEAP[test.exe]: Invalid Address specified to RtlFreeHeap( 770000, 555620 )调用堆栈:
NTDLL! 77f97704()
NTDLL! 77fb6688()
NTDLL! 77fb58fe()
NTDLL! 77fa7111()
NTDLL! 77fcbeda()
TEST! free + 45 bytes
TEST! _freebuf + 24 bytes
TEST! fclose + 39 bytes
........
size_t __cdecl fread (
void *buffer,
size_t size,
size_t count,
FILE **stream
)
请再次检查你的dll和exe是否都使用的同一CRT库。
最好都连接多线程的dll版本
另外,我想问的是,你的环境和我的相同吗,VS.Net + Win 2K + SP3
exe使用单线程CRT dll,结果出现assert failed后来都使用多线程dll运行成功
class MyFile{
virtual int open(...){
m_fp=fopen(...);
}
virtual int read(...)
{
return fread(...);
}
... FILE *fp;
};
exe传递MyFile*给dll以访问文件方法一定要是virtual的