SOS:关于多线程中内存传递及释放的问题

cber 2001-09-06 03:56:40
一个程序,有一主控线程及多个辅助线程。现在我们在辅助线程中申请了一块内存,把指向它的指针传递给主控线程,然后在主控线程中删除掉这块内存。结果在Release版本中,我们在debug它时发现:在删除内存时有exception抛出。
辅助线程与主控线程之间并没有任何的同步或互斥机制,采取了轮换时间片的方式协同工作:-(
指针的传递是通过往主控线程中发消息时把指针作为消息的lParam传递过去的
由于是马上要release出去的版本,所以不可能在现在对整个程序进行大的改动,而且在整个程序中又大量地使用了上面的方法,因此希望各位高手能够指点出一个暂时可行的解决方案,谢谢。
附示例代码如下:
//主控线程
MainThread::processmessage(wParam, lParam)
{
//do the message-drived action
delete lParam;
//告诉辅助线程消息处理完毕
}
//辅助线程
AssistandThread::genmsg()
{
p = malloc(size);//此处与delete不匹配,但不是问题的重点所在
//prepare msg
msg.lParam = p;
PostThreadMessage(mainThrId,msg,wParam,lParam);
//以下是我所说的轮换时间片的工作方式实现
while(1)
{
//当得到从主控线程中发送过来的消息被处理完毕的机制时
break;
}
//other actions
}
...全文
208 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
cber 2001-09-10
  • 打赏
  • 举报
回复
依然没有得到我想要的答案,算了,给分。
richen 2001-09-07
  • 打赏
  • 举报
回复
我觉得还是线程之间同步和互斥没有处理好。试着只启动一个线程试试。
zj_ok 2001-09-07
  • 打赏
  • 举报
回复
gz
cber 2001-09-07
  • 打赏
  • 举报
回复
alwaysakid:
你的方法类似于我们讨论的下一步准备改成的方法,但现阶段可能不会采用:(

>注意p只能是单纯的内存快,不能是具有析构函数的指针
这话不假,但我们这个struct没有其他的内容,只是一个类似于C中的struct的结构体,所以还能勉强通过。
wlrwx 2001-09-07
  • 打赏
  • 举报
回复
不知道你的程序中是否使用了如下的一些宏操作:

#ifdef _DEBUG
...
#else
...
#endif

如果有的话,那么就有可能导致内存的问题了,也就是说在你的DEBUG版中释放了,而RELEASE的时候去没有相关的代码释放分配的空间,不过,有个简单的办法可以解决你的问题,如下描述:

首先,你如果是使用 new 和 delete 来分配和释放内存的话,那么,先改用 malloc 和 free 来分配和清除,相信效果是一样的。
其次,你自己封装malloc和free函数如下:

void* _malloc( char* tip, int nBytes )
{
void* _p = malloc( nBytes );
//在这个地方加入代码,把tip信息及malloc返回的地址指针写到日志文件中
return _p;
}

void _free( void* p )
{
//在这个地方加如代码,把该指针地址写到日志文件中
free(p);
}

最后,在所有你要分配空间的地方加入一个唯一的标志字符串,在你的程序运行直到出现内存泄露以后,去察看日志文件(或者做一个日志分析器),把分配过的地址及删除过的相同地址都删除掉,剩下的就是分配了没有释放的,在根据你的tip标志去找分配的地方,然后根据你的程序查流程,就知道什么地方该释放而没有释放了...

不知道我是否说清楚了我的想法了,欢迎大家指正:)


}
vcmfc 2001-09-07
  • 打赏
  • 举报
回复
to cber:我恐怕最段上不了网,收信也不行,现在部门上网严打呀!,上阵子有人跑到成人站点,而且上网人多,老板回来上网其慢,令我们的老大给个答案呀!,所以已经好久没有来CSDN了。
vcmfc 2001-09-07
  • 打赏
  • 举报
回复
to cber:不好意思,我被老大封了上网ID,现在才收到你的信;以下是我的看法:其实你是否发现你定义的char sz[1],你们的代码是不是使用="";来赋值的,如果是sz就被扩大了,所以如果你用你的原malloc()在分配字节数上再+1,我想应该可以free()掉,这是我以前碰到的一个问题。

to nosky2000:如果你没有调用WIN API,GetLastError()返回是0.
蒋晟 2001-09-07
  • 打赏
  • 举报
回复
建议不要使用可变长度的结构,可以多保存一个指针,像这样
class A{
a(){m_nDataSize;=0;m_lpData=NULL;}
UINT m_nDataSize;
LPVOID m_lpData;
}
m_lpData初始化为NULL,使用时分配内存,在析构函数中释放m_lpData内存。这样虽然麻烦一点,但是安全。
如果数据是一个CObject对象,可以省去m_nDataSize,因为系统会根据指针指向的对象类型判断调用什么析构函数。
onsky2000 2001-09-07
  • 打赏
  • 举报
回复
我没能找到这个错误,不过WINDOWS有一个查错函数或许能帮助你。
GetLastError()返回错误码,必须紧跟在错误后面,如果是WIN2000可以用FormatMessage()得到错误文本,其它的,去winerror.h找到文本看一看什么错误。不过不知道程序运行到
delete后能否接着运行,调试版应该可以把错误码找到。
cber 2001-09-07
  • 打赏
  • 举报
回复
今天我们把delete p换成了delete[] p,问题解决(我曾经将它换成free((void*)p)也不行)。这是一个很丑陋的解决方法,但现阶段只能这么做着了:(
我苦思很久,找不出任何一个理由来解释这种做法。根据Effective C++中所说的使用配套的new/delete对,以及我以前的C++的知识,我实在无法得到那样的做法,希望能有高手给我就这个问题详细解释一下。
如果在下周一没有得到更好的建议的话,这100分我就全部给jiangsheng了。
lpt 2001-09-07
  • 打赏
  • 举报
回复
用NEW DELETE 很方便的。
Great_Bug 2001-09-07
  • 打赏
  • 举报
回复
蒋晟 2001-09-07
  • 打赏
  • 举报
回复
mystruct* p = (mystruct*)malloc( sizeof(mystruct) + len_other_data );??
那你就不能用delete了
alwaysakid 2001-09-06
  • 打赏
  • 举报
回复
最简单的解决方法是使用单一的堆
把相应的malloc(size)改为 HeapAlloc(GetProcessHeap(),0,size);
把相应的delete p 改为HeapFree(GetProcessHeap(),0,p);

注意p只能是单纯的内存快,不能是具有析构函数的指针
Soft21 2001-09-06
  • 打赏
  • 举报
回复
大家好啊,我在等待大家的答案,呵呵!
cber 2001-09-06
  • 打赏
  • 举报
回复
请问你试的是Debug版还是Release版。
我们做的也和你差不多,只不过我们的指针指向的是一个struct,而且它还是一个可变长度的struct,参见如下:
struct mystruct{
//...
char sz[1];//以此来实现可变长度的struct
}
然后我们的内存分配就使用了如下的语句:
//这也是我最不能忍受的一种方式,但以前的代码确实是这样写的:-(
mystruct* p = (mystruct*)malloc( sizeof(mystruct) + len_other_data );

然后在Debug版本中没有任何问题,但在Release版本的Debug过程中就老是有exception抛出。
蒋晟 2001-09-06
  • 打赏
  • 举报
回复
我试过可以传递一个CPtrList的指针。在一个线程里面new出来,添加一些数据,然后Post到另外一个线程处理,最后delete
cber 2001-09-06
  • 打赏
  • 举报
回复
Sorry,我忘了讲,p是一个指针,不是句柄。虽然Win32编程中的句柄大多数都是用指针来实作出来的,但这里的指针就是指针,不是句柄,而且我也试过将delete p换成free(p),这样也没有得到预期的效果。
您的建议我们也讨论过了,不过由于版本发布在即,而那样的改动将会导致比较多的工作,所以现在暂时不考虑。你知道,有时为了维护已有的代码,我们只有不停地使用一些超常规的方法:-(

而且,在Debug版中,上述问题不复存在。
蒋晟 2001-09-06
  • 打赏
  • 举报
回复
p = malloc(size);//此处与delete不匹配,但不是问题的重点所在
这个就是问题的重点所在。句柄不应该用delete删除

可以用一个全局映射存储数据(参见CMap),然后在线程之间传递键值,或者直接使用内存映射文件。

15,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧