Chinaunix首页 | 论坛 | 博客
  • 博客访问: 931827
  • 博文数量: 158
  • 博客积分: 4380
  • 博客等级: 上校
  • 技术积分: 2367
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-21 10:45
文章分类

全部博文(158)

文章存档

2012年(158)

我的朋友

分类: C/C++

2012-11-26 09:40:01

1。在对字符串赋值前,必先用memset进行全部赋零操作
有人说这么安全。不知道证据从哪儿来的?
有人说多这一句也不多。不知道多哪一句才算多?

2。对于不再使用的指针变量,赋零
有人说这么安全。不知道证据从哪儿来的?
有人说多这一句也不多。不知道多哪一句才算多?

--------- 以下是俺觉得内容太少,而拉过来凑字数的,不是闲得发慌的话,不需要看 ---------

这两个恶习估计唯一的作用就是隐藏Bug,令错误难于被发觉。(这句话转自 chinaunix 上的一位牛人,深表赞同 )

第1个恶习,有个好例子,在论坛上出现过
char str[16];
memset( str, 0, 16 );
str[0] = 'a';
str[1] = 'b';
str[2] = 'c';
printf( "%s", str );
如果没有memset这一句,结果就是错误的,所以他认为数组赋值前先memset一下是个很好的风格。
(正确的做法是str[3] = '\0')

对于 位比较 不在此列,比如将 str[16] 送入加密函数 void foo( void* p, size_t n )
那么 "abc \0 1" 和 "abc \0 2" 就是不等同的,在论坛中也见到过两次,有人问“我用DES3加密一个字符串,每次输入都是abc,但结果却不一样”,呵呵。

第2个恶习,就是重复释放的问题
int* p = new int;
delete p;
p = 0;
delete p;
如果没有p = 0;这一句,结果就是错误的,所以他认为这也是个很好的风格。
(正确的做法是删除重复的delete p。我们的目的是去除错误,而不是让错误不产生危害

对于p = 0 某些人(只是某些人而已)会用来在Debug版本中做释放检查,算是一种debug的手段,但不应该出现在正式的代码中。
而其实,一般的编译器都会在debug版本中做类似的行为,但绝不是 p = 0 这种傻叉叉的做法,而是 *(int*)p = 特值。
例如
p = new char[100];
p1 = p;
delete[] p; *(int*)p = 0xFEEEFEEE;
如果 *(int*)p1 == 0xFEEEFEEE 说明 p1 指向的内存已经被释放
阅读(5195) | 评论(28) | 转发(0) |
给主人留下些什么吧!~~

网友评论2012-11-26 09:44:21

山丘之王
问题讨论到现在,我觉得不管是采用**的作法,或者是接纳7猫的作法,都有充分的理由.

上面的讨论让大家明白了很多.

网友评论2012-11-26 09:44:11

周星星
“这个不再使用的p1居然还是有可能在后面用到的,防御性编程就是使用一种工具去挽救愚蠢的我们” --- 这句话,以及随后的一段我未能看明白。

    p = new 。。。
    使用 p
    delete p;
    p = 0; // 这一句
    p = new 。。。
    使用 p
    delete p;
有没有中间 p = 0 这一句,都不影响后面对p的使用。

    p = new 。。。
    使用 p
    delete p;
    p = 0; // 这一句
    使用 p<

网友评论2012-11-26 09:44:00

周星星
我明白你的意思,也接受你的观点,但我不认可的是你用 p = 0 来做事例。
因为 p = 0 唯一的作用就是 重复释放时不会报错也不影响逻辑的正确性。但什么时候会出现重复释放这个小问题呢?
a. 拷贝时多拷贝了一行delete p;
b. 退出时(包括进程和类实例)确保所有的内存资源都释放掉。
除了b是可以勉强接受的之外,a是难以接受的,因为只多拷贝了一行delete p的几率太小,大部分情况下会拷贝多行,而这些多出来的非delete p行几乎100%的会导致逻辑运行的错误。其实拷贝错误大部分是因为拷贝了相似的代码,但未能将所有相关变量名修改过来,这必然会导致逻辑运行的错误。第三种情况,完全就是变量名写错了,这还是会导致逻辑运行的错误。
所以我的观点是 一旦出现重复释放的错误,必然伴生着更为严重的逻辑错误。而如果通过p=0来掩盖重复释放的错误,即同时掩盖了更为严重的逻辑错误。

网友评论2012-11-26 09:43:47

zuilang
以星星和7猫为代表:
星星做法:程序员都是负责的,甚至都(应该)是完美的,一旦前面的程序员出现错误,就必须想尽一切办法暴漏出来。
7猫做法:程序员都是不负责的,甚至都(极可能)是愚蠢的,后面的程序员必须假设前面的程序员很有可能出错,并且想尽一切办法不要受前面的笨蛋的影响。

星星是完美主义者,学院派:程序出现了错误,眼里容不下沙子,哪怕其实程序的逻辑可以继续运行下去,但是为了避免后面出现更大的错误,必须立即检查前面的错误,也许现在要停机3个月损失数百万,但总比2年后损失数千万更好。
7猫是(我不知道该怎么说):程序出现了错误,只要后面的程序员能够容错,不影响他自己的逻辑,或者说他有办法跳过去,ok,就这么样继续下去吧,反正即使解决了这个错误,“肯定”还会有其它错误,无所谓,也许到程序结束生命都没有大问题呢。

这里的前后程序员也指同一个程序员的“前”和“后”代码

事实是,7猫的做法更为普遍,也是软件工程接受的做法,或

网友评论2012-11-26 09:43:34

周星星
delete p;
。。。此处有N多行代码
delete p;
如果代码是这样写,当错误发生时,怎么去查找错误?

------ 检查的方法有很多,最简单的就是通过内存窗口看p指向处的内容,在debug模式下如果p指向处的内存已经被删除,则p指向处的内存会被赋上特定值。
还有一种预防的办法,是我很久很久前的一篇文章,大体是将变量作用域通过花括号缩减到其需要的域中,不让它溢出来。这样可以在编译期就将很多错误暴露出来。
当然这些都不是重点,重点是“当错误发生时”,我知道需要去查找错误,而你连“当错误发生时”都不知道。请问当这种错误发生时,你如何肯定的认为只要加上p=0后一切就会没事了?
从另一个方面来佐证,假如加上p=0后一切就会没事了,那么
a. C++标准应该会规定delete p后p自动归零。但C++标准没有这么规定。
或者
b. windows应该在delete 重复释放p时不报错,连写