免费注册 查看新帖 |

Chinaunix

广告
  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: llj
打印 上一主题 下一主题

delete对象的内存泄露问题 [复制链接]

论坛徽章:
0
31 [报告]
发表于 2011-11-08 10:15 |只看该作者
回复 27# 狗蛋

我是说默认placement new不是用delete释放的……所以说new/delete必须配对有点不严密。(好吧,语言的阴暗面,但有可能用的话就没法回避。)

论坛徽章:
0
32 [报告]
发表于 2011-11-08 11:03 |只看该作者
回复  狗蛋

我是说默认placement new不是用delete释放的……所以说new/delete必须配对有点不严密。(好 ...
幻の上帝 发表于 2011-11-08 10:15



    哦,这样啊……

我不认为“new/delete必须配对”这句话不严密。

你说的问题,和new[]/delete[]必须配对是一样的,和getRef()/Release()以及malloc/free都必须一一对应也都是一回事,都和new/delete无关了。


事实上,不仅是内存管理:申请屏幕句柄一样要归还;申请锁一样要归还;有进临界区就必须有对应的出操作……等等等等。

归根结底一句话,资源的申请和归还必须一一对应;而且这个一一对应并不仅仅是有申请就有释放,而是怎么申请就怎么释放(哪怕你简单的用宏转调用一下new,也要同时搞个转调用delete的宏。否则将来稍微一扩充……),并且原则上,谁申请的,就由谁释放。

论坛徽章:
0
33 [报告]
发表于 2011-11-08 11:29 |只看该作者
有多线程的话,这样ref和unref本身就有问题
w_anthony 发表于 2011-11-08 09:33


如果unref写成这样:

unref()
{
    if( --count == 0 ) delete this ;
}

    多线程环境可以吗?

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
34 [报告]
发表于 2011-11-08 11:39 |只看该作者
如果unref写成这样:

unref()
{
    if( --count == 0 ) delete this ;
}

    多线程环境可以 ...
llj 发表于 2011-11-08 11:29



不行的++i和--i都不是原子操作,你可以写测试程序证实。
windows上有InterlockedIncrement和InterlockedDecrement保证加减的原子性,实际上就是汇编locked前缀指令保证的。
linux上我不知道有没有直接的api,不过可以用内嵌汇编抄InterlockedXXX系列的代码,再调用。

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
35 [报告]
发表于 2011-11-08 11:39 |只看该作者
本帖最后由 w_anthony 于 2011-11-08 11:41 编辑

网络卡,发重了,编辑掉

论坛徽章:
0
36 [报告]
发表于 2011-11-08 11:51 |只看该作者
不行的++i和--i都不是原子操作,你可以写测试程序证实。
windows上有InterlockedIncrement和Interlo ...
w_anthony 发表于 2011-11-08 11:39



    不光++i和--i不是原子操作,if( 0==count ) delete this更加不是原子操作。

完全可能在count和0的比较尚未返回或刚刚返回、甚至 delete this执行一半时线程切换,有人又调用了getRef……


if( 0==count ) delete this这种写法,是对线程编程完完全全的误解和无知。因为这里需要保护的,是整个A/B对象,而不仅仅是一个count变量。

经典的高效singleton实现用flag避免每次探测对象状态都加锁,是仅仅在检测对象状态是否有效时;真正建立/修改/删除对象,一样要用锁整个保护起来。
不了解这个根本,盲目模仿,只能画虎不成反类犬……

论坛徽章:
9
摩羯座
日期:2013-08-15 15:18:48狮子座
日期:2013-09-12 18:07:47金牛座
日期:2013-09-16 13:23:09辰龙
日期:2013-10-09 09:03:27白羊座
日期:2013-10-17 13:32:44子鼠
日期:2014-04-23 15:09:38戌狗
日期:2014-09-17 11:37:542015年亚洲杯之韩国
日期:2015-03-26 10:16:442015亚冠之武里南联
日期:2015-08-18 14:55:52
37 [报告]
发表于 2011-11-08 12:21 |只看该作者
如果unref写成这样:

unref()
{
    if( --count == 0 ) delete this ;
}

    多线程环境可以 ...
llj 发表于 2011-11-08 11:29



刚才没看清楚,你那个count是Atomic类型,那--count == 0应该可以……

论坛徽章:
0
38 [报告]
发表于 2011-11-08 13:33 |只看该作者
本帖最后由 狗蛋 于 2011-11-08 13:35 编辑
刚才没看清楚,你那个count是Atomic类型,那--count == 0应该可以……
w_anthony 发表于 2011-11-08 12:21



    这没有用。

Atomic类型的意思,是指定编译器将变量内存地址对齐,避免读写操作跨内存边界/页面边界/cache边界时是非原子性的。

我之前说过,int 变量读写并不被c/c++编译器或CPU保证是原子的,原因就是对齐是不保证的(虽然几乎100%的编译器都会做……但你不一定就碰不上哪个变态编译器;而且万一其它人在某个头文件加个pack(1),更是彻底死翘翘)。而atomic保证这点。


但,虽然对aomic变量的读/写操作是原子的;先读其值,然后在这个值上加减1的incr类操作,仍然是非原子的。想得到原子的incr,就必须 atomic_incr 之类指令的支持或者自己加合适的总线lock前缀。

论坛徽章:
0
39 [报告]
发表于 2011-11-08 13:50 |只看该作者
本帖最后由 llj 于 2011-11-08 13:52 编辑
这没有用。

Atomic类型的意思,是指定编译器将变量内存地址对齐,避免读写操作跨内存边界/页面 ...
狗蛋 发表于 2011-11-08 13:33



    你说的很对,是我没有说清楚。

  真实是, 我做了封装;重载了++,--, 操作符; 而且确实使用了atomic_incr 之类指令,保证其操作是原子性。

论坛徽章:
0
40 [报告]
发表于 2011-11-08 14:04 |只看该作者
你说的很对,是我没有说清楚。

  真实是, 我做了封装;重载了++,--, 操作符; 而且确实 ...
llj 发表于 2011-11-08 13:50



    ++ --就是安全了,还有delete this

你仍然没法保证自己正在delete this时,另外一个getRef过来了……
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP