注册 登录  
 加关注

网易博客网站关停、迁移的公告:

将从2018年11月30日00:00起正式停止网易博客运营
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

为着理想勇敢前进

 
 
 

日志

 
 

安全的语言——C++  

2007-08-18 01:42:57|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
我这篇文章是错误的,请不要相信我这篇文章所说的。我现在没有删掉它只是为了让大家来批判的。
嘿嘿,聪明的读者,你们知道我这篇文章错在哪里吗?

如果你只用 Java ,你宣称,你写的 Java 代码绝对不会崩,如果崩了肯定是 JVM 的错,或者是你调用了有问题的 JNI 方法,这是理所当然的,Java是安全的,JVM保证这个安全。

但是,如果你用C++,你要是敢宣称,你写的C++代码绝对不会崩,估计会有很多人来崇拜你的。嗯,举个例子,我现在就敢宣称,我写的C++代码绝对不会崩,你们来崇拜我吧,哈哈。

好,现在告诉你们为什么我可以被你们崇拜:
首先,崩的定义,崩的定义就是非正常退出,不过有一点例外,自己主动assert不算崩,那属于正常逻辑检查,因为,任何assert都可以改写成抛出异常,所以不算崩。那么,哪些情况会崩呢?
1、数组越界。
2、访问已经被释放的内存区域。
3、访问空指针。
4、多线程访问共享数据而没有适当的同步。
5、强制转换成错误的类型,并且访问了不存在的成员。
6、编译/连接的时候的兼容问题。也就是 DLL Hell 之内的东西。
7、调用 C 风格的函数,需要传递指针。

我绞尽脑汁,就只想出这7种情况会崩,这7种情况,根据我的编码规范,我都是可以无一例外,完全避免的。
1、数组越界
不使用任何原生数组,改用boost::array,boost::array的operator[]加入了内存越界的assert检查,如果真的内存越 界,按上面所说的崩的定义,主动assert不算崩,因为主动assert可以非常容易的跟踪调试解决。所以不会你取出来一个已经越界的值,然后把这个值 赋值到另外一个地方,然后在十万八千里以外用到了这个值指向的某个不存在的内存。然后崩掉。然后你就找不到崩的原因了。

2、访问已经被释放的内存区域。
这个容易,不到万不得已,不用new,一定要用new的地方,一定让boost::shared_ptr和new连用。只要做到这一点,你自己的代码一定不会访问到被释放的内存区域。不过这并不是最好的解决办法。最好的解决办法是期待C++0x的垃圾收集。

3、访问空指针。
这个更简单,不用指针,改用引用。引用在初始化的时候赋值,初始化以后引用就不能改变,所以绝对不会有空指针。一定需要用指针的复杂算法,改用基于iterator和range的算法。基于range的算法,我上一篇日志推荐的P-Stade就是做这个用的。

4、多线程访问共享数据而没有适当的同步。
我写的所有多线程程序中,多线程之间都必须保证零共享数据,线程间通讯全部用消息。

5、强制转换成错误的类型,并且访问了不存在的成员。
正常情况下只对值类型进行强制转换。这样就绝对不会转换出一个错误的类或者结构的指针。
不过有一个例外,有一个trick,就是ATL式的向派生类转换,仅仅只有这种情况下才用static_cast,在这种特定情况下,派生类实质上只是作为基类的事件handler存在的,这种情况下,强制转换是安全的。
除了这个例外,其他所有忍不住想要用强制转换的地方,用模板和虚函数都是可以代替的。

6、编译/连接的时候的兼容问题。也就是 DLL Hell 之内的东西
动态链接库必须动态链接到 CRT ,这一点在 Linux 下是强制要求, Windows 没有强制要求,但这是我自己给自己的强制要求。
如果需要生成动态连接库,则这个库只有一个入口函数是导出函数,其他所有函数都是虚函数。任何公开接口都有虚析构函数。接口中参数传递要么是 POD 类型,要么就是 const 的引用。做到这些,就可以完全保证谁分配谁释放了。
保证编译器所有涉及ABI的设置都一致。

7、调用 C 风格的函数,需要传递指针。
不用 C 风格的函数,用标准 C++ 库和 Boost 。

只要绝对做到以上所说的规范,就一定不会崩。



  评论这张
 
阅读(435)| 评论(5)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018