免费注册 查看新帖 |

Chinaunix

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

脱裤子放屁的代码…… [复制链接]

论坛徽章:
0
101 [报告]
发表于 2007-08-10 12:28 |只看该作者
别以为养成了 NULL 的习惯,遇到非 NULL 指针就是合法可用的!

论坛徽章:
0
102 [报告]
发表于 2007-08-10 12:28 |只看该作者
原帖由 mmmixx 于 2007-8-9 21:38 发表

在 C 里,的确如此,在 C++ 里就不然了。







舍本求末的做法,干嘛为了掩盖一个错误而引进更多的(潜在)错误呢!按照这种说法,它分分钟可能将合法的指针值变成非法的指针值,也可能将 NULL 指针 ...

我确实可能没有你学C++懂,只是拿它写了5年以上几十万行的代码了. 你说的两个依据:一说delete 空指针不会core dump, 二说new对象内存不够时会默认抛出异常. 请你自已拿程序到各种UNIX平台试试再说吧, 包括AIX, SCO, HP. 从我这么多年调试程序的结果来看, delete空指针没有一次不CORE的. POSIX 只是规范, 但不是每个编译器都能完全符合的, 再说了, 还有象SCO之类的老版本CC编译器呢. 看书本重要,实际经验在应用中更重要.
前人总结的规范, 自然是有其道理的, 若不是交过学费, 谁愿意做多此一举的事情?

论坛徽章:
0
103 [报告]
发表于 2007-08-10 12:48 |只看该作者
等接触到递归下降的代码, 就知道判断NULL的必要性了, 很多地方的调用路径是不可预期.

当然我接触的是C代码.

看postgresql的内存管理, 后台内存释放函数不允许传空指针.

复杂调用无法预期指针是否被释放(我见过的就是语法分析, 优化程序属于复杂递归下降分析). 这也是GC出现的重要原因吧.

论坛徽章:
0
104 [报告]
发表于 2007-08-10 13:03 |只看该作者
看着一阵一阵的晕。。。
茴香豆的写法啊。。。。

论坛徽章:
0
105 [报告]
发表于 2007-08-10 13:04 |只看该作者
确实楼主接触的程序有局限,在不同应用中,对程序的要求是不同的,在某些程序中,可能这个是没太大必要的,但是要考虑更多复杂的大型并发程序。

论坛徽章:
0
106 [报告]
发表于 2007-08-10 13:07 |只看该作者
当你的代码要跨平台,跨编译器的时候,良好的变成习惯非常重要!

论坛徽章:
0
107 [报告]
发表于 2007-08-10 13:09 |只看该作者
原帖由 zszyj 于 2007-8-10 12:28 发表

我确实可能没有你学C++懂,只是拿它写了5年以上几十万行的代码了. 你说的两个依据:一说delete 空指针不会core dump, 二说new对象内存不够时会默认抛出异常. 请你自已拿程序到各种UNIX平台试试再说吧, 包括AIX, ...



"从我这么多年调试程序的结果来看, delete空指针没有一次不CORE的"

我对这个真的很好奇...
可以说一下这么多年你都是在什么平台下调试程序吗?

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
108 [报告]
发表于 2007-08-10 14:06 |只看该作者
第二个未见上下文,不知道是否有必要。


第一个很有必要。

从保存信息的角度看,一个指针有否被delete/是否被初始化,除非能确定运行时上下文,否则是绝对无法判断的。

而delete后将指针置为NULL,则明白无误地向使用者传递了这么一个信息:此指针已失效,切勿引用。

推而广之:为准确识别指针有效状态,任何一个指针——无论下文中是否还要用到——只要它还在,就必须在delete后置空。

否则,就和引用未初始化的变量一样,需要考虑代码编写者的资质了。


同理,任何可能留下无法确认有效性的指针的代码,都是不合格的;作者的资质都值得怀疑。
(比如:
     p2=new(...) ;
       p1=p2;
       delete p2;
....
这个代码段过后,只要p1、p2还存在,就必须保证p1和p2都为NULL。否则是代码作者的责任。
因为没有任何机制,可以去识别一个非NULL的指针是否有效指针。




因为delete一个NULL指针而core dump,和由于delete一个野指针而core dump,性质上是完全不同的。

因为,前者加个判断即可规避;后者却需要花费N倍的精力去查找野指针产生的根源。
(何况现代c++标准还规定delete NULL指针是安全的。)


所以,有必要再强调一次:
   任何时候,任何一个可访问的指针,都必须指向有效内存空间或指向NULL。

不能保证这点的程序员,请另谋高就。
因为你能解决的问题,比你所带来的麻烦多得太多。



进一步,基于如上讨论,我们进一步看是否应该置空已经删掉的对象的内部指针。


首先,这个指针是否还有可能访问?

很明显,如果所有程序员都很细心,很敬业,那么这个指针必然是不可访问的。
因为对象已经删掉,指向它的所有指针必然已经是NULL。(程序员保证!!)

在这种情况下,置空对象内部指针,纯属脱裤子放屁。


那么,如果有个程序员不够敬业,delete对象后没有置空呢?

很可能会有人去访问那个已经删除了的对象!

如果置空了这个对象内部指针,那么我们立刻就会发现,某个对该对象的访问出了问题,问题原因是对象内部指针无效(为NULL)。
进一步分析原因,显然很快就能找到问题源头。

但要是没有置空这个指针,那么我们只能发现:某个对该对象的访问除了问题,问题原因未知——似乎是野指针,但也可能是其他问题(因为这个对象内部指针指向的空间也许还没来得及被覆盖)。
这种情形下,要排查错误,就是不折不扣的海底捞针了。


换句话说:一个置为NULL的指针,为代码排错保留了至关重要的信息。
这个信息明确告诉代码维护人员:问题可能发生范围到此为止,不必到处乱找了!


另外:
    对象内部指针置空,并不能保证已失效的对象不被覆盖。这确实会导致“指针置空”这个预防措施失去作用。
    但是,被覆盖的对象内部信息必有变化。只要是debug老手,很容易就能看出此对象内部各字段的取值有问题,有被覆盖的痕迹(比如,连续的两个int,现在可能保存了一个字符串。这就是个再明显不过的“对象被覆盖或未初始化”标志)。

    即使无法看出对象有否被覆盖,但在某些对象未被覆盖的特殊情况下,可以迅速缩小排查范围,代价不过是多写一个无害的指针置空语句:还算合算吧?

    何况,除非内存再分配非常频繁或/和内存非常紧张的系统,覆盖一个被删除对象,是需要不少时间的(相对于CPU来说)。
    至少,比很多人所想当然的要长。



最后:
    编程规范解决的是风格上的问题。它的目的有:
        1、减少笔误式bug的发生率,以免因为低级错误导致程序crash;(如多人协作时的命名风格规定等)
            2、利用编译器机制,尽可能在早期暴露“笔误”式的bug(如 == 和 = 等);
        3、尽可能保留运行时信息,以便在错误发生时迅速定位问题(如无效指针必须保证为NULL等)
        4、透过特别的技法,提醒使用者自己的设计思路(如非虚拟析构函数就等于告诉使用者“请勿从本类继承”——这会在使用者犯错时通过编译器曲折地提醒他)

可能还有一些目的,我一时也总结不全,就暂时这样吧。
(所谓的编程规范是为了代码风格统一论,本人并不认同。代码是为了实现功能,并不是为了好看——虽然,不好看的代码肯定好不了;好的代码肯定很“好看”:但这只是编程规范的边际效应,绝非制定它的主要目的)

    指针delete后置空,就是一个典型的编程风格问题。请勿将它与代码逻辑混为一谈。
(因此,如果LZ所列的第二条是不考虑上下文、当作编程规范强制推广的话,那确实是脱裤子放屁)

论坛徽章:
0
109 [报告]
发表于 2007-08-10 14:31 |只看该作者
这个贴子真闹热, 我也凑两个字.

我经常这样写程序:

if (p) {
   free(p);
   // p = NULL;  这个地方看情况, 不一定都加
} else {
   // 警告处理
}

这样的好处是, 如果我在什么地方犯了错或者程序逻辑上有问题, 我就可以在调试的时候及时知道是那个地方的问题.  再就是不会CORE DUMP (最不喜欢的东西)

还有其它类似的"多余"代码.

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
110 [报告]
发表于 2007-08-10 14:33 |只看该作者
assert似乎就是告诉程序员,只有在测试覆盖全部assert代码时,assert才是安全的保证。
对于小工程,试乎可以保证,但对于像OS这样的大工程,可以保证测试全覆盖吗?
若没有全覆盖就出Release,是否可能意味着意想不到的错误呢?

PS: 本人对assert的用法深表疑虑。当然有比没有好。但有不意味着可解决一切问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP