翻译《有关编程、重构及其他的终极问题?》——5.使用工具去分析你的代码

翻译《有关编程、重构及其他的终极问题?》——5.使用工具去分析你的代码

标签(空格分隔): 翻译 技术 C/C++
作者:Andrey Karpov
翻译者:顾笑群 - Rafael Gu
校验者:高国栋
最后更新:2016年12月04日


本书背景说明、总目录等介绍,可以跳转到以下链接进行查看:
http://blog.csdn.net/headman/article/details/53045891

欢迎大家转载,但请附上原作者以及翻译者的名字、原文出处,以尊重光荣的劳动者。

5.使用工具去分析你的代码

这段代码是从LibreOffice项目中拿出来的,PVS-Studio诊断后发现错误: V718 The ‘CreateThread’ function should not be called from ‘DllMain’ function(译者注:大意是CreateThread不能在DllMain中被调用,DllMain是Windows上Dll的入口初始化函数,因为Dll是被其他程序嵌入调用的,调用DllMain时有多种状态,我推测作者当时是在此Dll未被宿主程序加载时调用了CreateThread,此时就会报错).

BOOL WINAPI DllMain(HINSTANCE hinstDll, 
                    DWARD fdwReason, LPVOID lpvReserved)
{
    ....
    CreateThread(NULL, 0, ParentMonitorThreadProc, 
                 (LPVOID)dwParentProcessId, 0, &dwThreadId);
    ....
}

解释
我过去有段很长时间作为一名freelancer(译者注:即网上从专门的网站接货,一般在自己家干)。有一次我接了个活,但最后没有完成。因为这个活本身就不合理,但我当时没有发现,而且这个活给人第一感觉是简单和清晰的。

当时需要在DLLMain中,在特定的情况下用Windows API执行一些动作,我不记得具体那些动作了,只记得那一点都不困难。

因为这些代码不能正常工作,导致我花了很多时间在上面。它们能在一个新的独立的程序上工作,但不能在DllMain中工作。因为魔法吗吗?反正当时我没有办法找到出错的原因。

直到现在,直到我研发PVS-Studio很多年以后,我才突然意识到那次问题处在哪里。在DllMain函数中,你只能执行很少的一些动作,因为这个时候Dll还没有被调用程序加载,所以你不能调用任何运行时相关的函数(译者注:作者应该忘了DllMain中可以检测Dll被调用程序加载的状态,其实可以检测到DLL被调用程序加载后的状态)。

现在,当类似一些不合理的操作在DllMain函数中被发现时,我们就可以通过一些工具的诊断去警告程序员。

细节
更多关于DellMain使用的细节你可以在CSDN上的相关文章上发现:Dynamic-Link Library Best Practices(作者这里列出了很多CSDN摘抄来的代码,主要都一些DLL和DllMain的相关基础知识,特别是DllMain中不可以做什么,因为现在的变成很少用到Windows的DllMain,所以译者不打算翻译,如果有需要可以直接去前面MSDN的链接去看)。

正确的代码
前面从LibraOffice项目摘取出来的代码有可能工作、也有可能不工作——事实上,这依赖于运气。

要修复这样的错误其实不容易。一般来说,你需要重构你的代码,尽量使得DllMain中的代码越简单越好。

建议
其实这很难给出什么建议,因为你不可能知道所有事情(译者注:比如知道DllMain的所有CSDN知识),所以每个人都会或多或少遇到类似的神秘问题。如果一定要给正式的建议的话,那么就是:你应该认真的把你程序所用到的所有相关文档都仔细阅读一遍。但是你也肯定知道,一个人不可能预知到所有的问题,所以当你读了所有的文档,也许你就没有时间去编程了。并且,即使你已经阅读了很多页,你也不能保证你没有遗漏一些让你遇到麻烦的知识。

我希望我能给你一些像样的实践中的建议,但不幸的是,我只能建议:用PSV-Stduio的静态分析器。当然,它不能保证你发现所有bug。自从这些年以来使用了静态分析器,我已经节约了很多时间。之前我经常因为解决不了某些问题而变得发怒或者发狂,现在这种情况也大大减少了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值