来自 关于计算机 2019-11-14 16:52 的文章
当前位置: 六合联盟网 > 关于计算机 > 正文

软件中的错误采摘战术

 

一、用C++ 而不是 C
1.用const代替#define来创制常量
2.用enum代替#define来创设常量集结
3.用内联(inline)函数代替#define宏
4.用new和delete代替malloc和free
5.用输入输出流(iostreams)代替stdio
6.筛选C++语言并不是C预管理,但是要明白调节和测量试验代码的时候须要动用预微处理器
7.检查实验浮点指针的值。浮点指针没有确切的二进制表示法,所以不用期待它们会有准确的值。因而,也不应该用相比八个浮点指针的值的秘诀来判断双方是不是等于。eg:
#include<float.h>
if (fabs(floatValue - 42.0) < FLT_EPSILON ) ...;
这里FLT_EPSILON 是浮点值的最大表示抽样误差,而DBL_EPSILON是双浮点值的最大表示测量误差。
8.如果在VC++中使用dynamic_cast,记住要在project中设置Enable Run_time Type Information选项
9.假诺循环变量的加码操作在每趟循环的时候都不得不实践的话,那么就用for语句替代while语句。eg:
POSITION pos;
int line;
for(line = 0,pos=linelist.GetHeadPosition();
    pose!=0;
    line++,lintlist.GetNext(pos)) {
.....
}
10.若是构造函数真的供给虚函数,那么就选拔单独的八个开头化函数好了。
11.承保析构函数中的分外在析构函数内部得随处理。最后,要保障基类的析构函数是虚函数。那样,固然对象是一个对准基类的指针,也会调用派生类的析构函数。不然,假使基类的析构函数不是虚函数,就能够唤起能源泄漏(resource leak)。

    Error = 0 的顺序是子虚乌有的,怎么着搜聚和管理程序中的错误?如何更加好地行使错误新闻的访谈和申报来扶持程序的调护治疗?如何让产品公布后,顾客能够反映出更有价值的难题音信?那几个难题是本文就要涉及的,近期对友好所做项目中的错误管理机制做了有个别总括与思维,故在这里研究,希望对咱们具备利于。

二、使用断言
12.用MFC时选择ASSERT宏
13.不要选用VE大切诺基IFY宏,使用断言宏
14.在选用CObject派生类的指标在此以前都要调用ASSERT_VALID宏
15.接连在调用ASSERT_KINDOF宏以前调用ASSERT_VALID宏
16.移植代码的时候也移植断言
17.要想有效的施用断言必要自然的战术,不要随便的把断言分布到您的代码里面,而是据守有个别已经济建设立起来的情势
18."Assert the word",是说:不要试图选择哪二个预感要开掘错误,而是依照你的预知攻略断言一切
19.最有力的断言是用来注明变量之间的原则性关系。那个关乎称为不改变关系(invariants)。此中,类不改变关系和循环不变关系最佳管见所及
20.企划程序的还要就陈设不改变关系,在写代码从前知道它们,并且为它们成立文书档案
21.国有成员函数比个人和维护成员函数须求更康健的断言
22.丰硕完结AssertValid函数,不要选用MFC ClassWizard提供的私下认可完成
23.提出对AssertValid函数选用上面的预感格局:
void CMyObject::AssertValid()
{
 //  check the immediate base class first
 CMyObjectBaseClass::AssertValid();
 
 // check the data members not in the base class
 ASSERT_VALID(m_pObject1);
 ASSERT_VALID(m_pObject2);

    这段日子,依照作者个人的知晓,软件中的错误搜集和上报形式首要好似下三种:

 // now check the class invariants not checked by the base class
 // be sure to document the invariants
 ASSERT(m_Value != illegalValue);
 ASSERT(m_Object1.GetSize() == m_Size);
 ...
}
24.不得法的施用断言会引致错误。断言是用来发表错误的,并非用来纠正运营时刻错误的。
25.如若你的前后相继是防范性的,别忘了使用断言。假设您接收断言,也别忘了防范性编制程序。那三种技术最佳结合在一块使用。
26.思考采纳_ASSERTE(FALSE)来简化学防治御性的编制程序和断言的组成。要想获取更有描述性的预知音讯,思量采用_ASSERTE("Problem description." == 0)。
27.断言不是错误管理的取代品。
28.这种办法让您绝不打扰窗口画图就能够在出现窗口后,任何时候观看招致断言失效的代码。
void CMyview::OnDraw (CDC* pDC) {
 int previousReportMode = _CrtSetReportMode(_CRT_ASSERT,
     _CRTDBG_MODE_DEBUG):
 CMyDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 ...  // draw the window
 if (previousReportMode != -1)
  _CrtSetReportMode(_CRT_ASSERT,previousReportMode);
}
29.行使GetObjectType函数来断言一个兼有有效句柄的GDI对象(察看再次回到值是否为零卡塔 尔(英语:State of Qatar),可能有些特定的GDI对象(察看再次来到值是或不是是有个别特殊值卡塔 尔(英语:State of Qatar)。eg:
_ASSERT(GetObjectType(hBrush) == OBJ_BRUSH);
可是,要开掘到GetObjectType函数只怕回到一些让人大吃一惊的结果。如,上面包车型大巴预见失效:
HBRUSH hBrush = CreateSolidBrush(RGB(0,0,0));
DeleteObject(hBrush);
_ASSERTE(GetObjectType(hBrush) == OBJ_BRUSH);
因为深米色的刷子是二个备用设备的指标(约等于不能够去除卡塔尔国,由此 DeleteObject 函数调用就从不效应。
30.MSDN文书档案声称IsBadCodePtr、IsBadReadPtr、IsBadStringPtr和IsBadWritePtr那多少个API函数在收取到坏指针的时候就能够在调解版本里以致断言失效。这么些说法是大错特错的,必得把那一个函数包装在断言语句中。

先是种方法:使用常用的音讯输出语句。

三、使用追踪语句
31.OutputDebugString API函数,MFC AfxOutputDebugString 宏和MFC AfxDumpStack 函数在全数版本中均被编写翻译,然而别的具有的追踪语句仅在概念了_DEBUG符号时,技巧被编写翻译。
32.跟踪语句不能够满含程序代码或对程序代码有间接的熏陶效应。追踪语句的指标是向程序猿提供音讯,并不是客商。
33.与断言的分别:
(1)跟踪语句是无条件的。断言是有标准化的布尔语句,而追踪语句却总能够实践。
(2)追踪语句不直接显示bug。断言用于体现出bug,而追踪语句用于呈现程序实践和变量值。
(3)追踪语句能够被随意的忽略。暗许情形下,断言打断程序的施行,并弹出叁个音信框等待客户或程序员的响应;追踪语句则将新闻输出到调节和测量检验窗口或文件中,于是相当轻易被技术员忽视。这种特性使得追踪语句对于全体上前后相继的查实和次序的警示是特别卓越的。二个很好的类比是:断言对编译器错误,追踪语句对编写翻译器警报。
34.void OutputDebugString(LPCTSTOdyssey traceText),那么些windows API函数是Windows的黄金时代局地,因而它一贯是立竿见影的,那使得那么些函数适用于在程序运转和终止进程中的追踪。与此相反,Visual C++的C运营时刻函数库和MFC追踪语句并不适用追踪程序运营和竣事,因为它们仅在加载了它的DLL之后才使得。假若你只想在调节和测验版本中应用OutputDebugString,能够应用上面包车型大巴宏来达成:
#ifdef _DEBUG
#define OutputTranceString(text) OutputDebugString(text)
#else
#define OutputTranceString(text) ((void) (0))
35.ANSI C++运转时刻函数库中并不曾追踪语句,可是它有用于跟踪的正式字符格局的输出流,具体有:C语音的stderr流和C++语言的cerr 和 clog流。stderr不须要缓冲区,cerr使用单位缓冲,clog使用完全缓冲。
36.运用MFC Tracer工具来支配MFC本人输出的追踪语句
37.追踪语句的管用应用需求一个国策,太多的追踪新闻会稳中有降它们的管事。如下是八个基本的追踪语句计策:
 (1) 调节和测量试验器补充政策:使用追踪语句补充由人机联作式调节和测量试验器提供的音讯
 (2) 调节和测量试验器代替攻略:使用追踪语句代替人机联作式调节和测验器
38.选用综合确诊追踪语句能让您查看程序中最引进注指标事件;使用特殊确诊追踪语句来化解二个格外的标题;生机勃勃旦鲜明的难题已经化解,将用以特殊确诊的跟踪语句删除。
39.在交互作用式调节和测量检验器不能缓慢解决难题的意况下,如:调节和测验服务器、跨机器调节和测量试验(如DCOM)、夸程序设计语言调试际遇编制程序语句、跨进度调节和测量试验蒙受进程、调节和测量检验线程、远程调节和测量试验、遭遇这些因为海森堡不分明原理而很难调节和测验的程序动作。使用追踪语句消弭难题。
40.追踪调节和测量检验本领
 (1)使用DebugView实用程序
 (2)思考提供二个重定向输出设置
 (3)管理长字符串
 (4)管理多量的追踪输出
 (5)发生调节和测验报告
 (6)输出独立行,而且不要忘记了新行(newline)字符
 (7)别忘了检查追踪语句
 注意:每当你的主次中有荒诞而你想赢得越来越多音讯的时候,你应当去查看一下追踪新闻

    对于调整台程序,能够动用 printf 语句或许 std::cout 将错误音信打字与印刷出来;对于MFC程序,可以选用 TRACE 宏,将错误音讯输出到 output 窗口,或然应用 MessageBox直接弹出对话框将错误消息告知客户。

四、使用特别和重返值
1.接收再次来到值管理错误供给程序猿严厉的编制程序作风,程序员无论是还是不是有这种习贯,这都以丰硕不希望的。
2.无可否认的不胜管理是C++中的二个常识。相当通过产生错误非确定性信号,能够让程序代码和错误管理代码分开,并且不会让程序忽视错误。
3.必需询问使用了哪一种错误管理方法,重回值照旧抛出十分。假使不精晓,那么您的次序一定有标题。
4.老大是依附每一个线程而建议并拍卖的;格外无法被线程忽视,必需被管理;未管理的那多少个会使进度甘休,而不独有是线程停止;非常管理在刑满释放栈时会放出具备的栈对象,因而防止了财富的尾巴;分外管理要求大量的附加操作,使得它并不适应日常运转的代码。详细的说,catch块有风度翩翩对开垦(overhead),但是try块有非常少的开销;由此唯有在抛出特别的时候才会有那些的十一分操作开支;你能够抛出任何类型的非凡对象,但不包括整数。
5.重返值能够提醒不荒谬和不正常的函数运维,但不可能阻止线程的连续运转;再次来到值十分轻便被忽视;重回值在独立的意况下是二个整数,日常映射符合于叁个预约义的值;再次回到值能高效的传递和吸收接纳;
6.全数的非错误的情景音信都应当选取重临值
7.再次来到值用于大许多场合下得以轻巧忽视而不会身不由己难点的错误
8.在循环中的错误管理必需赶快,因为那多少个的额外开支,所以为了拿走越来越好的习性,使用重返值是两个更加好的选择。在此种景观下,倘若您真要使用十二分,能够创立一个函数来将再次回到值转变未丰硕。
9.使用于中间语言模块中的错误。
10.采取Windows API的错误管理机制。用SetLastError设置错误代码,通过GetLastError检查测验这些错误代码。
11.从C++格外管理的视角看,故障应该被感到是错误。
12.您一定要运用/Eha调试器选项来扑获使用C++至极操作机制的操作系统格外。
14.Windows布局十分管理:使用_try,_except,_finally,_leave关键字和RaiseException API函数;由Windows协理,不适于别的操作系统;不管理C++对象的解析;作为硬件非常或操作系统卓殊的结果抛出,也可用作RaiseException函数结果被抛出。
15.C++卓殊管理:使用try,throw和catch等根本字;仅被C++语言扶持;管理C++对象的剖析;能够抛出任何类型的C++对象。卓殊对象能够从正式的卓殊基本类派生,也得以从别的类派生,也许它们也足以是松手的品种;作为throw语句的结果被抛出。
16.Visual C++ 使用结构非凡管理体制达成C++万分。
17.协会特别管理不可能管理目的的分析,由此你应当在C++程序中央机关单位接选取C++非凡。不过,因为C++非常不能管理硬件和操作系统格外,你的先后须求将组织特别转变为C++极度。
18.为了准确管理硬件和操作系统非凡,你能够创建谐和的老大类并使用_set_se_translator函数安装七个布局十分向C++非常的转变器。
19.不要扑获那个不能够还原所发出难点的转速后的结构特别。
20.在比超少抛出拾分的状态下使用极度的代价并不是相当大,而且这么做真正能够拉长质量。
21.特别计谋中最要紧的风华正茂有的其实便是有一个国策。不要在其后弥补。
22.不行扑获法规:扑获微处理器按梯次提供;如若扑获微处理器扑获了扳平品种或针对同风姿浪漫品种抛出对象的指针,则应扑获非常。倘若扑获微处理机扑获了二个公家基类也许指向三个公家基类抛出目的的指针,则应扑获非常;一个简便扑获微机扑获任何类型的要命,因而它总是放在最后。
23.概念一个丰富基类来管理程序代码抛出的特别。
 class CProgramException : public exception {
 public:
 CProgramException (const _exString &_what_arg) :
  exception(_what_arg) {}
};
选择CProgramException类使得格外管理特别简便易行,因为可以经过管理这种基类扑获全部的顺序中的极度。假诺须求的话,也得以利用额外的积极分子数量系数描述特定的难题。
24.使用auto_ptr恐怕一个像样的指针类通过限定部分变量的动态分配来机关释放能源:
void LeakFreeFunction (int arg) {
 auto_ptr<CMyObject> pObject(new CMyObject(arg));
 ... // do something that throws an exception
 // can still call member functions as normal
 pObject->MemberFunction();
 // no need to delete pObject
}
注意:auto_ptr仅在接收delete释放财富时利用。
25.使用非常管理更简约,更牢靠,更使得,能够成立更完善的代码。可是,你应该只介惦念不到的气象下采纳非常管理。借让你以为二个指针应该时间和空间值,这种条件下就一直在代码中检查这几个值,而并不是使用非常。
26.非MFC的C++相当应该通过援引来扑获。使用引用扑获极度不必要删除相当对象(因为运用引用扑获的要命会在栈中传送卡塔尔,何况它保留了多态性(因而你扑获的不行对象便是你抛出的可怜对象卡塔尔。使用指针扑获特别须求您剔除对象,而使用值扑获对象会招致对象的“分片”(slicing),也正是说,将派生的非凡对象转变为扑获的数据类型。
27.MFC要命应该经过指针来扑获。因为它们平时从堆中分红,当你管理完格外之后,你必要调用Delete成员函数:
...
catch (CFileException *e) {
 // handle file exception
 ...
 e->Delete(); // required to prevent a memory leak
}
所以,你不尚可简便扑获微处理机扑获MFC十分,因为者会引致五个内部存款和储蓄器泄漏。你必需利用Delete成员函数删除MFC相当,而毫不用delete操作符,因为有的MFC相当作为静态对象创造。
28.即使扑获了十一分,你能够由此施行下列标准动作的片段组成来拍卖它:
 (1) 什么也并不是做。
 (2) 改正那一个难题不分厚薄试代码。
 (3) 纠正这一个难点但不要重试代码。
 (4) 就算顾客需求的话,向客商体现错误消息。
 (5) 假使现身的主题素材不是前后相继不当的话,输出叁个确诊的追踪音讯。
 (6) 假设现身的难题是前后相继不当,输出一个预知。
 (7) 在日记文件中著录这几个主题材料。
 (8) 假如那三个是不行复苏的,截至进度的运维。
 (9) 收拾已分配的财富。
 (10) 重新抛出这么些特别,使得尖端函数也能管理那一个丰盛,极其是在当前函数不能一心缓和的情形下。你能够再度抛出同贰个丰盛对象,或抛出一个新的那贰个对象。
29.和/EHa针锋绝没有错是联合格外(/EHs),并不是/GX。/GX实际上是/EHsc的简化形式。/GX表示编写翻译器应该即使extern "C" 的函数不抛出C++非常,而/EHs则抛出。
30.为客商和调用蒙受记录非常。平日,至极对象类型用于向调用项境布告现身的主题素材,而难题的陈说字符串用于向顾客通报。
31.Visual C++的默许意况下,new和malloc对于错误不会抛出卓殊,但您能够经过应用_set_new_handler安装七个Computer,让new针对不当抛出至极。你也足以让malloc通过调用_set_new_mode使用雷同微处理机。
#include <new.h>

    那一个管理政策往往针对于 “交互作用性” 的代码段,可以兑现 实时报告错误音信,以供客商实时地张开始拍录卖,避防前面发生更加大的失实。

class bad_alloc : public exception {
public:
 bad_alloc(const __exString& what_arg) : exception (what_arg) {}
};

第二种艺术:使用不当日志方式

int NewHandler (size_t size) {
 throw bad_alloc("Operator new couldn't allocate memory");
 return 0;
}

    思想:将次第中的全体错误音信输出到错误日志文件中,这样有以下这一个利润:

int APIENTRY WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,
        LPSTR lpCmdLine,int nCmdShow) {
 _set_new_handler(NewHandler);
 _set_new_mode(1);   // use NewHandler for malloc as well
 ...
}

    1.  当程序揭橥后,顾客在运用中境遇题目后,能够一直将错误日志发送给技术员,将非常的大地方便人民群众了难题的一向及原因的拆解解析。

32.如若已存在的代码中未有设定new重回空值,那么你应有一贯让new出错开上下班时间抛出一个十一分。
33.浮点数和整数不相仿,在暗许情形下它被零除不会现身相当,不过会现身一个要命意外的值"1.#INFO" (它表示那几个值并非一个数字)。要让检验浮点数难题更简便一些,你应当用如下的代码让浮点数错误抛出十三分。
#include <float.h>
int cw=controlfp(0,0);
cw &= ~(EM_OVERFLOW | EM_UNDERFLOW | EM_INEXACT | EM_ZERODIVIDE | EM_DENORMAL | EM_INVALID);
_controlfp(cw, MCW_EM);
浮点数极度微处理器必得调用_clearfp作为它的率先条指令来清空浮点数分外。

    2.  造福调节和测量检验十二线程恐怕关联互连网通信等复杂的主次,因为在如此的主次中,设置断点的调治将养格局特别地不便利,黄金年代旦中断在断点处,往往为唤起线程卓殊大概网络连接断开等主题素材,相当大震慑了调整的功用。倘使将错误音讯打字与印刷到文件中,错误描述详细充裕一些,能够相当的大地提升调节和测验的功用。

    3.  谋福程序进行遍布的性质测量试验。举例:C/S情势的体系,实行一百个顾客端对服务器的拜望测量检验,使用这种指鹿为马收罗战术能够方便地通过分析错误日志文件来臆度系统的质量。

    上边思谋那样三个难题:非常多软件的设计上都有多个好像TCP/IP公约的应用层的模块,该模块平常是一向与客商端交互作用的意气风发层,它隔开分离了焦点代码模块与顾客端的耦合,那么,对于那样大器晚成种档期的顺序结构相比较深技术方案,最底部爆发的错误消息怎么着传递到最上层?每后生可畏层都提供获取错误音信的接口?那样成本太大,也频频相当不足雅观,这该如哪儿理吧?

    小编想应该器重有以下二种管理政策,也便是笔者将在引出的荒唐搜聚和反馈的第二种和第多样政策:

其几种格局:C++非凡机制

    C++格外管理机制是八个用于有效地拍卖运转错误的特别苍劲且灵活的工具,它提供了越来越多的弹性、安全性和牢固性,制伏了古板艺术所带给的难题.

    十分的抛出和管理重要利用了以下四个重点字: try、 throw 、 catch 。

    抛出非常、捕获非凡,那么些是C++提供的十二万分方便地管理特别计策,能够实今后最后面部分抛出特别,由最上层捕获,何况管理。

    说真的,C++非凡机制真便是生机勃勃种管理错误和充足的很好的方针,若是急需选择该机制,需求从软件架商谈陈设时就要起初思量,意气风发旦软件结商谈代码写到一定水准后,再引入异常机制将很难达到很好的功能。其实,要想用好c++至极机制,不是黄金年代件相当轻易的事,非常是对于项目组里面有大气新人的时候,故使用资金如故挺高的。

    关于C++非常机制超多C++书籍都有介绍,小编也不在那赘述,本博客也是有风流洒脱篇C++至极机制的入门示例代码,风野趣能够看看

第各类艺术:GetLastError格局

    平时开垦windows程序的人相应都询问,windows程序有二个API:GetLastError,它事实上代表着一种错误采摘处理体制。 

    当二个Windows函数检测到三个破绽百出时,它会使用二个叫做线程本地存款和储蓄器(thread-localstorage)的机制。当函数重返时,它的再次回到值为flase就能够指美赞臣个荒诞已经发出。若要显明这是个什么错误,能够调用GetLastError函数来获得:该函数只回去线程的三贰十一位错误代码。

    WinError.h头文件包涵了Microsoft公司概念的错误代码的列表。

    当Windows函数运营退步时,应该立时调用GetLastError函数。借使调用另三个Windows函数,它的值很也许被改写。

    Visual studio还配有二个小的实用程序,称为Error Lookup.

    即使在编排的应用程序中发觉四个谬误,只怕想要向客户展示该错误的文件描述。Windows提供了叁个函数,能够将错误代码调换到它的文书描述。该函数称为FormatMessage。

    以上就是GetLastError方式的介绍,能够轻松地把它想象变为那样大器晚成种情势:有二个大局的变量,能够用来贮存三十三个人错误代码,生机勃勃旦Windows函数运营战败,就将错误代码赋值给这些全局的变量,每当调用GetLastError,则将该错误代码重回出来以供外界解析原因。

    其实,大家协和也足以落成那样叁个GetLastError情势的失实搜罗体制,收罗一切程序中时髦的错误新闻,供上层及时调用查询,定义自个儿的错误代码和谬误描述音信串,那么,如何技能更加好地落到实处归于本人的好像的乖谬搜集报告机制吗?怎么着使它具备越来越好地移植性、强壮性扶助七十八线程等卡塔尔和易扩充性参与新的错误代码和消息卡塔尔国呢?笔者将要后头的篇章中介绍本人的思谋和安排性。

    以上就是自家对软件中的错误搜罗计谋的动脑筋和小结,希望对各位有所扶助,也迎接我们建议意见和提出。

 

本文出自 “对影成几个人” 博客,请必须保留此出处

= 0 的顺序是海市蜃楼的,如何采摘和管理程序中的错误?怎么样越来越好地行使错误音讯的访问和反馈来帮衬程序的调和?怎么样让付加物发布后,...

本文由六合联盟网发布于关于计算机,转载请注明出处:软件中的错误采摘战术

关键词: