Chinaunix

标题: 如何有效的避免指针在释放之后被引用? [打印本页]

作者: Godbach    时间: 2008-11-07 11:50
标题: 如何有效的避免指针在释放之后被引用?
rt.这个问题如果只从理论上说,我们都明白这个道理,并且都知道要避免在指针释放之后再去引用它。

但是在实际的开发中,往往不少程序模块的BUG,都是因为这个问题引起的。前一段我和同事找出的网络设备的一个BUG也是这种情况,一旦发包过量设备就重启,原因是在有些条件下要释放,有些条件下又不不释放。还有一个同事解决的BUG也是这个原因。看来在实践中这个错误还是容易犯得。

想听一下各位在开发中有什么好的经验去避免这种情况?
作者: justkain    时间: 2008-11-07 12:03
引用计数。
作者: alexhappy    时间: 2008-11-07 12:09
释放之后赋值为NULL,引用之前检查是否为NULL
作者: snow888    时间: 2008-11-07 12:31
原帖由 alexhappy 于 2008-11-7 12:09 发表
释放之后赋值为NULL,引用之前检查是否为NULL


释放前赋值为 NULL
作者: ynchnluiti    时间: 2008-11-07 12:34
原帖由 snow888 于 2008-11-7 12:31 发表


释放前赋值为 NULL


作者: Godbach    时间: 2008-11-07 12:46
原帖由 snow888 于 2008-11-7 12:31 发表


释放前赋值为 NULL


释放之后吧,呵呵
作者: Godbach    时间: 2008-11-07 12:47
原帖由 justkain 于 2008-11-7 12:03 发表
引用计数。


这应该是一种方法
作者: ecjtubaowp    时间: 2008-11-07 12:49
林锐的<高质量C/C++编程>上有一些方法,可以看一下
作者: Godbach    时间: 2008-11-07 12:50
原帖由 ecjtubaowp 于 2008-11-7 12:49 发表
林锐的上有一些方法,可以看一下


这种方法在实践中不是很实用,个人感觉。
作者: 5毛党党员    时间: 2008-11-07 12:52
一般都是用释放后指向NULL,每次用之前都判断是不是等于NULL吧?
作者: tomorrow819    时间: 2008-11-07 12:53
原帖由 5毛党党员 于 2008-11-7 12:52 发表
一般都是用释放后指向NULL,每次用之前都判断是不是等于NULL吧?

似的
作者: Godbach    时间: 2008-11-07 12:54
原帖由 5毛党党员 于 2008-11-7 12:52 发表
一般都是用释放后指向NULL,每次用之前都判断是不是等于NULL吧?


大家在项目中都这样用吗?

其实如果用之前知道去判断的话,那也应该清楚前面有哪些地方做了释放的工作了。

[ 本帖最后由 Godbach 于 2008-11-7 13:19 编辑 ]
作者: LinuxKen    时间: 2008-11-07 13:06
原帖由 alexhappy 于 2008-11-7 12:09 发表
释放之后赋值为NULL,引用之前检查是否为NULL


这个办法可能是最简单的了。
作者: LinuxKen    时间: 2008-11-07 13:13
原帖由 Godbach 于 2008-11-7 12:54 发表



其实如果用之前知道去判断的话,那也应该清除前面有哪些地方做了释放的工作了。


为什么需要知道? 指向NULL的话,就算之前没有释放,那指针也是没法引用的啊。
作者: nicozhou    时间: 2008-11-07 13:16
之前有贴讨论过这个问题了。
个人习惯释放后不用(强制自己不用)。
作者: Godbach    时间: 2008-11-07 13:20
原帖由 LinuxKen 于 2008-11-7 13:13 发表


为什么需要知道? 指向NULL的话,就算之前没有释放,那指针也是没法引用的啊。


如果不知道去判断,那引用NULL指针就出问题了不是
作者: flw    时间: 2008-11-07 13:41
提高程序员的职业素养是关键。
要认真对待自己的工作,干一行,爱一行,精益求精,力图做到完美,但不因此而怠工。
作者: flw    时间: 2008-11-07 13:45
从某种程度上讲,那种所谓的 1 == a 和 free(p); p=NULL; 还有 memset(buf,0x00,sizeof(buf)); strcpy(buf,str); 等预防 BUG 的技巧恰恰是在阻碍程序员的成长。

写程序一定要注意语义,语义清晰,错误就会少很多。
建议每个 C 程序员都深入理解一下计算机语言的类型系统。
作者: alexhappy    时间: 2008-11-07 13:47
原帖由 flw 于 2008-11-7 13:45 发表
从某种程度上讲,那种所谓的 1 == a 和 free(p); p=NULL; 还有 memset(buf,0x00,sizeof(buf)); strcpy(buf,str); 等预防 BUG 的技巧恰恰是在阻碍程序员的成长。

写程序一定要注意语义,语义清晰,错误就会少 ...

阁下是个高手。。。。
作者: flw    时间: 2008-11-07 13:49
给大家推荐两本书:

types and programming languages :
http://www.paid4share.net/file/6 ... 0262162091-rar.html

advanced topics in types and programming languages :
http://depositfiles.com/en/files/1073133
作者: nhuczp    时间: 2008-11-07 14:24
这些主要还是看你实际情况中怎么去用。有时把释放放在goto后然后退出程序;这样做限可不必担心重用问题。
有时用一个变量去记录是否被释放。
作者: nhuczp    时间: 2008-11-07 14:27
原帖由 flw 于 2008-11-7 13:45 发表
从某种程度上讲,那种所谓的 1 == a 和 free(p); p=NULL; 还有 memset(buf,0x00,sizeof(buf)); strcpy(buf,str); 等预防 BUG 的技巧恰恰是在阻碍程序员的成长。

写程序一定要注意语义,语义清晰,错误就会少 ...


说的很好。程序写得好坏,BUG的多少主要在于你的思想。结构清不清晰,是否对整个要做的事情已经了解。
作者: cuur2008    时间: 2008-11-07 14:56
原帖由 flw 于 2008-11-7 13:45 发表
从某种程度上讲,那种所谓的 1 == a 和 free(p); p=NULL; 还有 memset(buf,0x00,sizeof(buf)); strcpy(buf,str); 等预防 BUG 的技巧恰恰是在阻碍程序员的成长。

写程序一定要注意语义,语义清晰,错误就会少 ...


你的意思是 if(1==a) 写法阻碍程序员的成长,而应该养成 if(a==1) 的书写习惯?
作者: Godbach    时间: 2008-11-07 14:57
原帖由 flw 于 2008-11-7 13:45 发表
从某种程度上讲,那种所谓的 1 == a 和 free(p); p=NULL; 还有 memset(buf,0x00,sizeof(buf)); strcpy(buf,str); 等预防 BUG 的技巧恰恰是在阻碍程序员的成长。

写程序一定要注意语义,语义清晰,错误就会少 ...


多谢flw版指点。也就是说想避免这样的问题,还是要靠自己写程序是逻辑清楚、语法正确,靠一些所谓的技巧去避免收效不一定明显。
作者: Godbach    时间: 2008-11-07 15:00
原帖由 cuur2008 于 2008-11-7 14:56 发表


你的意思是 if(1==a) 写法阻碍程序员的成长,而应该养成 if(a==1) 的书写习惯?


把最常用的东西用正确了,就应该可以保证程序的准确性。偶觉得flw版应该是这个意思
作者: safedead    时间: 2008-11-07 15:04
我以为flw会说:扣工资!
作者: emacsnw    时间: 2008-11-07 15:13
原帖由 cuur2008 于 2008-11-6 22:56 发表


你的意思是 if(1==a) 写法阻碍程序员的成长,而应该养成 if(a==1) 的书写习惯?


我觉得是。。。
作者: flw    时间: 2008-11-07 15:23
原帖由 cuur2008 于 2008-11-7 14:56 发表

你的意思是 if(1==a) 写法阻碍程序员的成长,而应该养成 if(a==1) 的书写习惯?

怎么说呢,虽然我反对 1==a 的理由不止这么一条,
但是接着刚才的话题往下说,
我认为如果一个人会不小心把 a==1 写成 a=1 且不自知
那说明他不是一个好的程序员,或者如果他是一个好的程序员,那么说明他的工作状态不好需要休息。

[ 本帖最后由 flw 于 2008-11-7 15:24 编辑 ]
作者: Godbach    时间: 2008-11-07 17:35
我认为如果一个人会不小心把 a==1 写成 a=1 且不自知,
那说明他不是一个好的程序员,或者如果他是一个好的程序员,那么说明他的工作状态不好需要休息。


状态好的时候认真写程序
作者: samon_fu    时间: 2008-11-07 17:39
标题: 回复 #1 Godbach 的帖子
这个东西就象工程中,大家都把read、write、malloc等函数包一层来使用一样的。

在工程中哪些东西最经常用的,你也可以包一下做成库来用。

比如你担心用了释放后的指针,那你包的时候只需要判断下对应指针 != NULL再用赛。如果=NULL了,那就打印错误出来。

这样错误不就好定位了。
作者: Godbach    时间: 2008-11-07 17:45
原帖由 samon_fu 于 2008-11-7 17:39 发表
这个东西就象工程中,大家都把read、write、malloc等函数包一层来使用一样的。

在工程中哪些东西最经常用的,你也可以包一下做成库来用。

比如你担心用了释放后的指针,那你包的时候只需要判断下对应指针 ...


多谢指点
作者: samon_fu    时间: 2008-11-07 17:48
标题: 回复 #28 flw 的帖子
要想成为一个好的程序员(?兄弟们别老想着程序员啊),习惯很重要。
而一个好习惯的养成始于态度。

兄弟们每写一行代码的时候,想着这代码以后要给自己看,就OK了:),

很多时候思路比写、调试代码重要,思路对了,什么都好办

[ 本帖最后由 samon_fu 于 2008-11-7 17:51 编辑 ]
作者: aaaab    时间: 2008-11-07 18:39
coding 要有code德
作者: honey709    时间: 2008-11-07 18:49
原帖由 samon_fu 于 2008-11-7 17:48 发表
要想成为一个好的程序员(?兄弟们别老想着程序员啊),习惯很重要。
而一个好习惯的养成始于态度。

兄弟们每写一行代码的时候,想着这代码以后要给自己看,就OK了:),

很多时候思路比写、调试代码重要 ...



习惯啊
习惯
码工就是可怜人儿
作者: 雨过白鹭洲    时间: 2008-11-07 19:08
原帖由 5毛党党员 于 2008-11-7 12:52 发表
一般都是用释放后指向NULL,每次用之前都判断是不是等于NULL吧?

或者不判断而让内核告诉你段错误
作者: nicozhou    时间: 2008-11-07 19:24
原帖由 samon_fu 于 2008-11-7 17:48 发表
要想成为一个好的程序员(?兄弟们别老想着程序员啊),习惯很重要。
而一个好习惯的养成始于态度。

兄弟们每写一行代码的时候,想着这代码以后要给自己看,就OK了:),

很多时候思路比写、调试代码重要 ...



如果只是自己看,那就用不着这样了,多数时候,你写的,别人看。
作者: samon_fu    时间: 2008-11-07 20:35
原帖由 nicozhou 于 2008-11-7 19:24 发表



如果只是自己看,那就用不着这样了,多数时候,你写的,别人看。



所以现在很多兄弟看别人的代码或者调试别人写的代码时很痛苦,乱的一塌糊涂。
还有就是很多兄弟应该有种感觉,就是自己写过的代码过段时间时打死都不想看了
作者: typadam    时间: 2008-11-07 21:34
原帖由 alexhappy 于 2008-11-7 12:09 发表
释放之后赋值为NULL,引用之前检查是否为NULL



这种方法没用.

在多线程里一点用也没

比如这个线程

p = *;

free(p);
p = NULL;

另一个线程
q = *;
还在继续用....程序就挂了.
这种技术虽然危险,在消息传递的时候还是有时候会放类似的错误.


最好就是引用计数,或者写个自已管理内存分配的调试跟踪机制.
作者: flyeleph    时间: 2008-11-07 23:32
最近刚完成一个项目。项目是在老外原有的代码上增加新的功能。以前写代码时习惯了在用指针前先检查一下指针是否为空。所以在这个项目也是这样做的。
但老外直接跟我们说不要那样干,那样会隐藏你的BUG。
想想也是有道理的。从逻辑上来讲,有时候根本不允许所用的指针为空,如果用判断来知道这个指针是空的,这时又要怎么办呢?输出一句话让调试的人
知道有错误了? 他们的做法是只在新申请的内存时检查是否为空,如果为空就做些内存清理的工作,腾出些空间。在其他用指针的环境下都不检查
指针是否为空。该调用方法的就调用方法,该往内存中写的就写。如果指针是空就让程序 crash 掉。这些能及时发现问题。如果不能及时发现问题,那只
能证明所做的测试还不够。
作者: Godbach    时间: 2008-11-08 15:39
原帖由 雨过白鹭洲 于 2008-11-7 19:08 发表

或者不判断而让内核告诉你段错误


如果我处理的是网络数据包,当内核遇上这样的NULL时,连OOPS都没有。内核告诉我,偶要重启了,呵呵
作者: Godbach    时间: 2008-11-08 15:42
这样说也有自身合理的地方。但是在内核中,有时出现这样的情况,那不但是程序crash,而是kernel panic,甚至OOPS都没有,直接重启了。

最近刚完成一个项目。项目是在老外原有的代码上增加新的功能。以前写代码时习惯了在用指针前先检查一下指针是否为空。所以在这个项目也是这样做的。
但老外直接跟我们说不要那样干,那样会隐藏你的BUG。
想想也是有道理的。从逻辑上来讲,有时候根本不允许所用的指针为空,如果用判断来知道这个指针是空的,这时又要怎么办呢?输出一句话让调试的人
知道有错误了? 他们的做法是只在新申请的内存时检查是否为空,如果为空就做些内存清理的工作,腾出些空间。在其他用指针的环境下都不检查
指针是否为空。该调用方法的就调用方法,该往内存中写的就写。如果指针是空就让程序 crash 掉。这些能及时发现问题。如果不能及时发现问题,那只
能证明所做的测试还不够。

作者: Godbach    时间: 2008-11-08 15:46
原帖由 samon_fu 于 2008-11-7 17:48 发表
要想成为一个好的程序员(?兄弟们别老想着程序员啊),习惯很重要。
而一个好习惯的养成始于态度。

兄弟们每写一行代码的时候,想着这代码以后要给自己看,就OK了:),

很多时候思路比写、调试代码重要 ...


确实,要有一个认真的心态。应该保证自己什么时候看,都可以看懂,不需要再想半天。那样别人看起来,可能就要想一个星期甚至更长时间。
作者: flw    时间: 2008-11-08 17:06
原帖由 Godbach 于 2008-11-8 15:39 发表

如果我处理的是网络数据包,当内核遇上这样的NULL时,连OOPS都没有。内核告诉我,偶要重启了,呵呵

内核不会这么差劲吧?
况且,重启也不是什么坏事情吧。
作者: Godbach    时间: 2008-11-09 11:05
原帖由 flw 于 2008-11-8 17:06 发表

内核不会这么差劲吧?
况且,重启也不是什么坏事情吧。


呵呵,可能这是因为我的内核模块的问题。因为在处理网络数据包的过程,当数据包超过某个pps时,系统直接就重启了。调试了很久,发现是因为当数据包量大时,网卡可能会丢包,程序里面kfree了。但是我后面又引用了skb。因为正常情况下,是可以引用的。后来解决问题的方法就是把这两行代码对调一下位置。
作者: smzgl    时间: 2008-11-09 11:44
// Template of smart pointer
// The class T must have Lock() & Unlock() methods
template<class T> class SmartPtr {
public:
        explicit SmartPtr(T *t = 0) : pt(t) { Inc(); }
        SmartPtr(const SmartPtr<T> & p) : pt(p.pt) { Inc(); }
        ~SmartPtr() { Dec(); }
        operator bool() const { return pt != 0; }
        T *operator->() const { return pt; }

        bool operator==(const SmartPtr<T> & p) const { return pt == p.pt; }
        bool operator!=(const SmartPtr<T> & p) const { return pt != p.pt; }

        SmartPtr<T> &operator=(const SmartPtr<T> & p) {
                if (pt != p.pt)
                        Dec(), pt = p.pt, Inc();
                return *this;
        }

private:
        void Inc() const { if (pt) pt->Lock(); }
        void Dec() const { if (pt) pt->Unlock(); }
        T &operator*();
        T *pt;
};



以上代码是GNUGK中的一个使用引用计数的模板。
作者: smzgl    时间: 2008-11-09 11:49
原帖由 flyeleph 于 2008-11-7 23:32 发表
最近刚完成一个项目。项目是在老外原有的代码上增加新的功能。以前写代码时习惯了在用指针前先检查一下指针是否为空。所以在这个项目也是这样做的。
但老外直接跟我们说不要那样干,那样会隐藏你的BUG。
想想 ...



你说的和我代码风格有些类似,不过我不是直接使用指针,而是如果指针为空直接exit,并输入信息。
如果直接使用指针,有时候未必能找到问题。因为有可能指针指向的内存被重新申请了,或者你从内存池获得的内存。到最后,出错的结果往往是莫名其妙的。
作者: smzgl    时间: 2008-11-09 11:58
原帖由 flw 于 2008-11-7 13:45 发表
从某种程度上讲,那种所谓的 1 == a 和 free(p); p=NULL; 还有 memset(buf,0x00,sizeof(buf)); strcpy(buf,str); 等预防 BUG 的技巧恰恰是在阻碍程序员的成长。

写程序一定要注意语义,语义清晰,错误就会少 ...


memset(buf,0x00,sizeof(buf)); strcpy(buf,str);


汗~我就经常这样些,要不每次只能
strcpy(buf, str);
buf[strlen[str]] = '\0';


我当年就专门就字符串拷贝自动加\0的问题,专门看了strcpy 和 strncpy的源代码。发现都不是我想要的。虽说strncpy能自动加\0,但也有例外。就是当str的长度等与n的时候,不会加\0

字符串拷贝就改成
strncpy(buf, str, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';

至于sprint 和snprint的代码看了头晕,就懒得去研究
作者: flw    时间: 2008-11-09 16:38
原帖由 smzgl 于 2008-11-9 11:58 发表
要不每次只能
strcpy(buf, str);
buf[strlen[str]] = '\0';

看来我说的还真是一点儿也没错。
确实是阻止了你的成长。

作者: flw    时间: 2008-11-09 16:40
> 至于 .... snprint 的代码看了头晕,就懒得去研究
最好用的函数居然懒得去研究……
而且我要再一次批评一下通过研究库函数的实现来研究库函数的功能这种做法。
作者: samon_fu    时间: 2008-11-09 18:26
标题: 回复 #49 flw 的帖子
不是有man手册吗? 想了解库函数的功能足够了啊。

另:在内核里,空指针确实是非常恐怖的一件事情,一般就是panic、crash, then reboot,呵呵。
经验丰富一点的,还是可以通过看寄存器里的东东来调试哦。
作者: samon_fu    时间: 2008-11-09 18:42
原帖由 flyeleph 于 2008-11-7 23:32 发表
最近刚完成一个项目。项目是在老外原有的代码上增加新的功能。以前写代码时习惯了在用指针前先检查一下指针是否为空。所以在这个项目也是这样做的。
但老外直接跟我们说不要那样干,那样会隐藏你的BUG。
想想 ...



怎么会隐藏BUG了?我们加判断是为了方便调试,测试的时候打印出来空指针的语句,难倒就不改了吗?
作者: smzgl    时间: 2008-11-09 20:01
原帖由 flw 于 2008-11-9 16:38 发表

看来我说的还真是一点儿也没错。
确实是阻止了你的成长。



那我想请问阁下,你是怎么拷贝字符串的?
malloc了直接copy吗?

如果buf是内存池分配出来的呢?

我写的程序需要拷贝字符串的地方,不是malloc出来的,就是从内存池出来,不确定buf是否被污染过。
而且snprint代码那么多,感觉效率没有strcpy高。

[ 本帖最后由 smzgl 于 2008-11-9 20:07 编辑 ]
作者: smzgl    时间: 2008-11-09 20:04
原帖由 samon_fu 于 2008-11-9 18:26 发表
不是有man手册吗? 想了解库函数的功能足够了啊。

另:在内核里,空指针确实是非常恐怖的一件事情,一般就是panic、crash, then reboot,呵呵。
经验丰富一点的,还是可以通过看寄存器里的东东来调试哦。



反正我初略的看了strncpy 和 snprint  没有看到哪里有说明最多的n个字符到底算不算\0,
后来仔细研究了E文,不放心才去看的代码
作者: retuor    时间: 2008-11-09 20:06
  看错了。

[ 本帖最后由 retuor 于 2008-11-9 20:08 编辑 ]
作者: flw    时间: 2008-11-09 20:08
原帖由 smzgl 于 2008-11-9 20:01 发表

那我想请问阁下,你是怎么拷贝字符串的?
malloc了直接copy吗?

如果buf是内存池分配出来的呢?

我通常用 strcpy,有时候也用 snprintf。
看需求了。
作者: flw    时间: 2008-11-09 20:10
原帖由 retuor 于 2008-11-9 20:06 发表
  看错了。

你没看错,看的很对。
作者: retuor    时间: 2008-11-09 20:32
原帖由 flw 于 2008-11-9 20:10 发表

你没看错,看的很对。


我以为他写的是


  1. buf[strlen(buf)]='\0'.
复制代码


这可比他那句强多了。
作者: flw    时间: 2008-11-09 20:33
原帖由 retuor 于 2008-11-9 20:32 发表


我以为他写的是


buf[strlen(buf)]='\0'.


这可比他那句强多了。

差不多吧。
前面还有一行 strcpy 呢。
作者: wuxb45    时间: 2008-11-09 20:50
赋值为null也不行阿,另一个引用依然会出错,我觉得还是封装一个内存管理类比较好
作者: hanliu2008    时间: 2008-11-09 21:08
释放后赋值NULL为好
作者: kuaizaifeng    时间: 2008-11-09 22:38
原帖由 flw 于 2008-11-7 13:49 发表
给大家推荐两本书:

types and programming languages :
http://www.paid4share.net/file/6 ... 0262162091-rar.html

advanced topics in types and programming languages :
http://depo ...


我晕,满书的数学符号
只能先orz了
作者: Godbach    时间: 2008-11-10 10:11
原帖由 flw 于 2008-11-9 16:38 发表

看来我说的还真是一点儿也没错。
确实是阻止了你的成长。


作者: chary8088    时间: 2008-11-10 10:27
也就是所谓的 “野指针”的问题
释放后,指向NULL
作者: bxfqing    时间: 2008-11-10 10:56
一直都是释放后赋值为NULL,学习了
作者: 怎么不对    时间: 2008-11-10 11:03
提示: 作者被禁止或删除 内容自动屏蔽
作者: flw    时间: 2008-11-10 11:40
原帖由 怎么不对 于 2008-11-10 11:03 发表
学习一下

多打打迷魂拳,然后好发广告,是不?
看你那一脸的 ADer 样!


作者: noword2k    时间: 2008-11-10 12:24
释放后置NULL是好习惯。

使用前不必检测是否为NULL,因为如果是NULL,程序直接崩溃,程序员能直接定位到崩溃点,进行DEBUG。

strcpy前是否用memset,要看接下来的运算,是把这段数据作为字符串用,还是作为一块数据来用。
如果作为字符串用,就没必要memset。
作者: Enrique_yu    时间: 2008-11-10 13:51
原帖由 flyeleph 于 2008-11-7 23:32 发表
最近刚完成一个项目。项目是在老外原有的代码上增加新的功能。以前写代码时习惯了在用指针前先检查一下指针是否为空。所以在这个项目也是这样做的。
但老外直接跟我们说不要那样干,那样会隐藏你的BUG。
想想 ...


确实是这样,但是定义指针时一定要初始化,free()后的指针一定要赋NULL值。这样可以避免不少问题
作者: wishel    时间: 2008-11-10 13:56
原帖由 noword2k 于 2008-11-10 12:24 发表
释放后置NULL是好习惯。

使用前不必检测是否为NULL,因为如果是NULL,程序直接崩溃,程序员能直接定位到崩溃点,进行DEBUG。

strcpy前是否用memset,要看接下来的运算,是把这段数据作为字符串用,还是作 ...


用NULL指针不是直接崩溃吧,应该会抛异常,不catch处理才会崩溃
作者: wishel    时间: 2008-11-10 13:59
当你的函数一定不能接受NULL指针的时候,用assert,而且即使在release版也开着
这叫design by contract
作者: noword2k    时间: 2008-11-10 14:25
原帖由 wishel 于 2008-11-10 13:56 发表


用NULL指针不是直接崩溃吧,应该会抛异常,不catch处理才会崩溃

catch让代码难看,执行时浪费系统资源,与其用catch,还不如直接检测指针是否为NULL。
作者: wishel    时间: 2008-11-10 15:13
catch让代码难看,执行时浪费系统资源


这两点都错。是你自己不会用。
作者: 312-pirl0    时间: 2008-11-10 18:13
在定义时,初始化为NULL,释放后也定义为NULL。引用是判断是否为NULL.
这可能是最安全的。
作者: crspo    时间: 2008-11-10 20:45
没啥办法,等者看pannic信息吧
作者: huxk    时间: 2008-11-11 09:55
c提倡的是,你知道自己在做什么,清楚自己在做什么

指针成为大问题,java等把指针去掉了,但是也不是不会出问题,bug也多得很

可是很难去掉人性的弱点,没有办法,只有小心再小心了,大脑一定要清晰,

可这也不是万全之策,大脑也有失灵的时候,上帝啊,这个世界就是这个样子
作者: sunnyfun    时间: 2008-11-11 14:07
野指针,C永远的痛,所以在其他语言出现了引用,去掉了指针。
自己包一个宏或函数,带计数的,多好。
作者: Godbach    时间: 2008-11-11 14:29
野指针,C永远的痛


呵呵,这个说法有点言过其辞了吧
作者: 思一克    时间: 2008-11-11 14:33
其实就是free后设置为NULL,

如果有非法引用, 系统立刻检查出来, 改正.
作者: rainysky    时间: 2008-11-11 16:25
原帖由 cuur2008 于 2008-11-7 14:56 发表


你的意思是 if(1==a) 写法阻碍程序员的成长,而应该养成 if(a==1) 的书写习惯?


我很同意flw的看法。不知道哪位高人想出来的if(1==a)这种写法。代码是写给人看的,不是写给机器看的。if(1==a)这种写法看上去不符合正常人的逻辑思维。

为了防止意外的错误,如果有可能,请把编译器的全部警告功能打开,然后解掉每一处警告。
作者: spurs    时间: 2008-11-11 21:07
一堆牛人啊,受教了,我是认真小心写,没有啥技巧...
作者: xie995    时间: 2008-11-11 23:17
原帖由 flw 于 2008-11-7 13:45 发表
从某种程度上讲,那种所谓的 1 == a 和 free(p); p=NULL; 还有 memset(buf,0x00,sizeof(buf)); strcpy(buf,str); 等预防 BUG 的技巧恰恰是在阻碍程序员的成长。

写程序一定要注意语义,语义清晰,错误就会少 ...

太同意flw这段话了。现在看见那些混乱不堪的代码就有气。认真些,那些隐藏bug的小技巧少用点。特别是memset,用多了真是受不了。
最近发现,好的程序,设计上都很清晰很简单,整个架构要有美感。那些实现起来很别扭的东西多半是设计不合理的结果。
作者: xie995    时间: 2008-11-11 23:24
原帖由 retuor 于 2008-11-9 20:32 发表


我以为他写的是


buf[strlen(buf)]='\0'.


这可比他那句强多了。

这种写法也不太好。strlen也要降低程序的效率,有时候是不可接受的。
大家写C主要就是图效率,降低效率的东西最好还是少用。有时候注意一下这些方面,效率提高一倍都可能。
作者: 狗蛋    时间: 2008-11-12 09:14
原帖由 flw 于 2008-11-9 20:33 发表

原帖由 retuor 于 2008-11-9 20:32 发表


我以为他写的是


buf[strlen(buf)]='\0'.


这可比他那句强多了。  


寒一个……

strlen本身就是靠查找'\0'的位置工作的,这句究竟是想干什么?
作者: 狗蛋    时间: 2008-11-12 09:15
找到'\0',再覆写一次'\0',然后心里就踏实多了?

难道这就是传说中的鸵鸟政策?

[ 本帖最后由 狗蛋 于 2008-11-12 09:18 编辑 ]
作者: wishel    时间: 2008-11-12 09:46
原帖由 狗蛋 于 2008-11-12 09:15 发表
找到'\0',再覆写一次'\0',然后心里就踏实多了?

难道这就是传说中的鸵鸟政策?


所以说最好是用strncpy,不过我从来不用c的库
作者: chzht001    时间: 2008-11-12 22:24
:wink:

[ 本帖最后由 chzht001 于 2008-11-12 22:26 编辑 ]
作者: flw    时间: 2008-11-12 22:40
原帖由 chzht001 于 2008-11-12 22:24 发表
:wink:

比方打得不贴切吧?
作者: 雨过白鹭洲    时间: 2008-11-12 23:05
原帖由 xie995 于 2008-11-11 23:24 发表

这种写法也不太好。strlen也要降低程序的效率,有时候是不可接受的。
大家写C主要就是图效率,降低效率的东西最好还是少用。有时候注意一下这些方面,效率提高一倍都可能。


我写代码从不把效率放在第一位,特别是所谓的优化技巧,花相当大的代价,换来的只是很小的性能提升,而且严重降低程序的可读性

只有程序性能核心部位或者性能瓶颈所在的地方,才需要特别关注效率
作者: flw    时间: 2008-11-12 23:09
原帖由 雨过白鹭洲 于 2008-11-12 23:05 发表


我写代码从不把效率放在第一位,特别是所谓的优化技巧,花相当大的代价,换来的只是很小的性能提升,而且严重降低程序的可读性

只有程序性能核心部位或者性能瓶颈所在的地方,才需要特别关注效率

严重同意!
非常赞同雨过白鹭洲的见解。
作者: JohnBull    时间: 2008-11-12 23:22
我有一个办法,写程序的时候,桌子上放一些小细绳,把左手的手指分别定义成锁、互斥量、堆空间...
加锁、锁互斥量、分配堆的时候,在口曲纸上写上变量名,用绳子系在相应的手指上,解锁、解锁互斥量、释放堆的时候,把它取下来,使用上述变量的时候看看左手...

JOKING~!

我觉得最好还是控制一下代码规模、模块封装要严密、程序的语义务必清晰,控制一个功能单位的代码行数不要超过2个屏幕(适当增加函数,函数也是天然的封装。效率?那是Intel的事),BUG自然就少了。代码一长,神仙也保不齐不出错。
作者: flw    时间: 2008-11-12 23:25
原帖由 JohnBull 于 2008-11-12 23:22 发表
我有一个办法,写程序的时候,桌子上放一些小细绳,把左手的手指分别定义成锁、互斥量、堆空间...
加锁、锁互斥量、分配堆的时候,在口曲纸上写上变量名,用绳子系在相应的手指上,解锁、解锁互斥量、释放堆的 ...

指头上绑绳子这做法挺 1 == a 的。
作者: Godbach    时间: 2008-11-13 15:56
原帖由 flw 于 2008-11-12 23:25 发表

指头上绑绳子这做法挺 1 == a 的。


作者: Godbach    时间: 2008-11-13 15:57
原帖由 雨过白鹭洲 于 2008-11-12 23:05 发表


我写代码从不把效率放在第一位,特别是所谓的优化技巧,花相当大的代价,换来的只是很小的性能提升,而且严重降低程序的可读性

只有程序性能核心部位或者性能瓶颈所在的地方,才需要特别关注效率


偶这里实现的就是网络数据包的处理,要修改数据包并发送回探包,应该是属于效率关注的地方。
作者: sunchiang    时间: 2008-11-13 16:09
JC同志说“超过一屏的程序总会有bug的”
作者: noword2k    时间: 2008-11-13 17:56
buf[strlen(buf)]='\0'.

这个确实太2了。
作者: smzgl    时间: 2008-11-13 20:15
摆脱,睁大眼睛看,我写的是
strcpy(buf, str);
buf[strlen(str)] = '\0'


看清楚了,不是buf[strlen(buf)] = '\0'

strlen是查找\0的,但是strcpy并没有把\0写入buf之中,何来重复而言.
strncpy仅在当源字符串长度小于n的时候,才会在buf后写入\0,当源字符串大于等于n的时候,并没有往buf写入\0,因此无法保证buf是以\0结束的.
作者: smzgl    时间: 2008-11-13 20:24
原帖由 雨过白鹭洲 于 2008-11-12 23:05 发表


我写代码从不把效率放在第一位,特别是所谓的优化技巧,花相当大的代价,换来的只是很小的性能提升,而且严重降低程序的可读性

只有程序性能核心部位或者性能瓶颈所在的地方,才需要特别关注效率



不知道阁下是否写过防火墙之类的软件,这些软件运行的时候对效率非常敏感.百兆环境下还好,千兆环境就很明显了.
作者: wishel    时间: 2008-11-13 20:48
原帖由 smzgl 于 2008-11-13 20:15 发表
摆脱,睁大眼睛看,我写的是
strcpy(buf, str);
buf[strlen(str)] = '\0'


看清楚了,不是buf[strlen(buf)] = '\0'

strlen是查找\0的,但是strcpy并没有把\0写入buf之中,何来重复而言.
strncpy仅在当源 ...


第一句的strcpy,只要str长过buf容量,就缓冲区溢出了。
假设系统没崩溃,继续往下进行
第二句buf[strlen(str)] = '\0',还是重复动作,因为strlen返回的值大于buf容量

strncpy标准用法:
strncpy(buf, src, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
len = strlen(buf);

[ 本帖最后由 wishel 于 2008-11-13 20:52 编辑 ]
作者: wishel    时间: 2008-11-13 20:50
原帖由 smzgl 于 2008-11-13 20:24 发表



不知道阁下是否写过防火墙之类的软件,这些软件运行的时候对效率非常敏感.百兆环境下还好,千兆环境就很明显了.


人家第二句提到了 只有程序性能核心部位或者性能瓶颈所在的地方,才需要特别关注效率
作者: flw    时间: 2008-11-13 20:56
原帖由 smzgl 于 2008-11-13 20:15 发表
摆脱,睁大眼睛看,我写的是
strcpy(buf, str);
buf[strlen(str)] = '\0'


看清楚了,不是buf[strlen(buf)] = '\0'

strlen是查找\0的,但是strcpy并没有把\0写入buf之中,何来重复而言.
strncpy仅在当源 ...



我实在想不出,
strcpy( buf, str );
buf[ strlen(str) ] = '\0';

buf[ strlen(buf) ] = '\0';
哪个更傻一些。

[ 本帖最后由 flw 于 2008-11-13 21:02 编辑 ]




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2