Rob*_*vey 8 c c++ pointers memory-leaks buffer-overrun
如果您是使用C或C++编程的人,没有内存管理的托管语言优势,类型检查或缓冲区溢出保护,使用指针算法,您如何确保您的程序是安全的?您是否使用了大量的单元测试,或者您只是一个谨慎的编码器?你有其他方法吗?
And*_*ith 24
上述所有的.我用:
实际上,我只是夸大其词.它不是太糟糕,如果你正确地构造你的代码,它实际上不太难控制资源.
有趣的说明.我有一个大型应用程序,它使用DCOM并具有托管和非托管模块.非托管模块通常在开发期间更难调试,但由于在其上运行了许多测试,因此在客户站点上执行得非常好.托管模块有时会遇到错误的代码,因为垃圾收集器非常灵活,程序员在检查资源使用时会变得懒惰.
ste*_*eha 16
我使用了大量的断言,并构建了"调试"版本和"发布"版本.我的调试版本运行速度远远低于我的发布版本,并且所做的所有检查都是如此.
我经常在Valgrind下运行,我的代码没有内存泄漏.零.保持程序无泄漏比采取错误程序并修复所有泄漏要容易得多.
此外,我的代码编译没有警告,尽管事实上我有编译器设置额外的警告.有时警告是愚蠢的,但有时他们指向一个错误,我修复它而不需要在调试器中找到它.
我正在编写纯C(我不能在这个项目中使用C++),但我以非常一致的方式做C语言.我有面向对象的类,有构造函数和析构函数; 我必须亲自调用它们,但一致性有帮助.如果我忘了打电话给一个析构函数,Valgrind会打我的头,直到我解决它.
除了构造函数和析构函数之外,我还编写了一个自检函数来查看对象并确定它是否合理; 例如,如果文件句柄为空但关联的文件数据未归零,则表示存在某种错误(句柄被破坏,或文件未打开,但对象中的那些字段中有垃圾).此外,我的大多数对象都有一个"签名"字段,必须设置为特定值(特定于每个不同的对象).使用对象的函数通常断言对象是理智的.
每当我malloc()有一些记忆,我的功能就会用0xDC值填充内存.未完全初始化的结构变得显而易见:计数太大,指针无效(0xDCDCDCDC),当我查看调试器中的结构时,显然它是未初始化的.调用时,这比零填充内存要好得多malloc().(当然0xDC填充仅在调试版本中;不需要发布版本来浪费那段时间.)
任何时候我释放内存,我擦除指针.这样,如果我有一个愚蠢的错误,代码在其内存被释放后尝试使用指针,我立即得到一个空指针异常,这指向我正确的错误.我的析构函数不接受指向对象的指针,它们接受指针指针,并在破坏对象后破坏指针.此外,析构函数在释放它们之前擦除它们的对象,因此如果某些代码块具有指针的副本并尝试使用对象,则完整性检查断言会立即触发.
Valgrind会告诉我是否有任何代码写下缓冲区的末尾.如果我没有那个,我会在缓冲区结束后放入"canary"值,并进行完整性检查测试它们.这些金丝雀值,如签名值,将仅调试版本,因此发布版本不会有内存膨胀.
我有一系列单元测试,当我对代码进行任何重大更改时,运行单元测试非常令人欣慰,并且有一些信心我没有可怕的破坏.当然,我在调试版本和发布版本上运行单元测试,所以我的所有断言都有机会发现问题.
将所有这些结构放置到位需要付出额外的努力,但每天都能获得回报.当一个断言触发并指出我正确的错误时,我感到非常高兴,而不是必须在调试器中运行该错误.从长远来看,一直保持清洁的工作要少一些.
最后,我不得不说我其实喜欢匈牙利表示法.几年前我在微软工作,和乔尔一样,我学习了匈牙利应用程序而不是破碎的变体.它确实使错误的代码看起来错了.
| 归档时间: |
|
| 查看次数: |
1564 次 |
| 最近记录: |