Credit:Moini[1]
作为一个程序员,我晓得我肯定会犯错误——怎么可能不错事!程序员也是人啊。有的错误能在编码过程中及时发觉,而有些却得等到软件测试了能够展现下来。但是,还有一类错误并不能在这两个阶段被解决,这就造成软件不能正常运行,甚至是提早中止。
假如你还没猜出是那个错误,我说的就是和显存相关的错误。自动调试这种错误除了历时,但是很难发觉并纠正。值得一提的是,这些错误很常见,非常是在用C/C++这类容许自动管理显存[2]的语言编撰的软件里。
辛运的是,现今有一些编程工具就能帮你在软件程序中找到那些和显存相关的错误。在这种工具集中,我评估了五款支持Linux的、流行的、自由开源的显存调试器:Dmalloc、ElectricFence、Memcheck、Memwatch以及Mtrace。在日常编码中,我早已用过这五个调试器了,所以这种评估是构建在我的实际体验之上的。
开发者:GrayWatson
评估版本:5.5.2
支持的Linux版本:所有种类
许可:CC3.0
Dmalloc是GrayWatson开发的一款显存调试工具。它是作为库来实现的,封装了标准显存管理函数如malloc,calloc,free等,使程序员得以检查出有问题的代码。
Dmalloc
就像工具的网页所示,这个调试器提供的特点包括显存泄露跟踪、重复释放显存doublefree[4]错误跟踪、以及越界写入fence-postwrite[5]检查。其它特点包括报告错误的文件/行号、通用的数据统计记录。
更新内容
5.5.2版本是一个bug修正发行版[6],修补了几个有关建立和安装的问题。
有何优点
Dmalloc最大的优点就是高度可配置性。例如说,你可以配置它以支持C++程序和多线程应用。Dmalloc还提供一个有用的功能:运行时可配置,这表示在Dmalloc执行时,可以轻易地启用或则禁用它提供的一些特点。
你还可以配合GNUProjectDebugger(GDB)[7]来使用Dmalloc,只须要将dmalloc.gdb文件(坐落Dmalloc源码包中的contrib子目录里)的内容添加到你的主目录中的.gdbinit文件里即可。
另外一个让我对Dmalloc爱不释手的优点是它有大量的资料文献。抵达官网的Documentation栏目[8],可以获取所有关于怎么下载、安装、运行、怎样使用库,和Dmalloc所提供特点的细节描述,及其生成的输出文件的解释。其中还有一个章节介绍了通常问题的解决方式。
注意事项
跟Mtrace一样,Dmalloc须要程序员改动她们的源代码。例如说你可以(也是必须的)添加头文件dmalloc.h,工具能够汇报形成问题的调用的文件或行号。这个功能十分有用,由于它节约了调试的时间。
除此之外,还须要在编译你的程序时,把Dmalloc库(编译Dmalloc源码包时形成的)链接进去。
但是,还有点更麻烦的事,须要设置一个环境变量,命名为DMALLOC_OPTION,以供工具在运行时配置显存调试特点,例如定义输出文件的路径。可以自动为该环境变量分配一个值,不过初学者可能会认为这个过程有点困难,由于该值的一部份拿来表示要启用的Dmalloc特点——以十六补码值的累加值表示。这儿[9]有详尽介绍。
一个比较简单方式设置这个环境变量是使用Dmalloc实用指令[10],这是专为这个目的设计的方式。
总结
Dmalloc真正的优势在于它的可配置选项。并且高度可移植linux修改环境变量 崩了,以前成功移植到多种操作系统如AIX、BSD/OS、DG/UX、Free/Net/OpenBSD、GNU/Hurd、HPUX、Irix、Linux、MS-DOG、NeXT、OSF、SCO、Solaris、SunOS、Ultrix、Unixware甚至Unicos(运行在CrayT3E主机上)。即使使用Dmalloc须要学习许多知识,而且它所提供的特点值得为之付出。
开发者:BrucePerens
评估版本:2.2.3
支持的Linux版本:所有种类
许可:GPLv2
ElectricFence是BrucePerens开发的一款显存调试工具,它以库的方式实现,你的程序须要链接它。ElectricFence能测量出堆[12]显存溢出和访问早已释放的显存。
ElectricFence
顾名思义,ElectricFence在每位所申请的缓存边界构建了虚拟栏杆,这样一来任何非法的显存访问就会造成段错误[13]。这个调试工具同时支持C和C++程序。
更新内容
2.2.3版本修补了工具的建立系统,致使-fno-builtin-malloc选项能真正传给GNUCompilerCollection(GCC)[14]。
有何优点
我喜欢ElectricFence的首要一点是它不同于Memwatch、Dmalloc和Mtrace,不须要对你的源码做任何的改动linux驱动下载,你只须要在编译的时侯把它的库链接进你的程序即可。
其次,ElectricFence的实现保证了形成越界访问的第一个指令都会造成段错误。这比在旁边再发觉问题要很多了。
不管是否有检查出错误,ElectricFence就会在输出形成版权信息。这一点十分有用,由此可以确定你所运行的程序早已启用了ElectricFence。
注意事项
另一方面,我对ElectricFence真正念念不忘的是它测量显存泄露的能力。显存泄露是C/C++软件最常见也是最不容易发觉的问题之一。不过,ElectricFence不能测量出栈溢出,并且也不是线程安全的。
因为ElectricFence会在用户分配显存区的前后分配严禁访问的虚拟显存页,假如你过多的进行动态显存分配,将会造成你的程序消耗大量的额外显存。
ElectricFence还有一个局限是不能明晰强调错误代码所在的行号。它所能做只是在测量到显存相关错误时形成段错误。想要定位错误的行号,须要利用GDB[15]这样的调试工具来调试启用了ElectricFence的程序。
最后一点,虽然ElectricFence能测量出大部份的缓冲区溢出,有一个例外是,假如所申请的缓冲区大小不是系统字长的倍数,这时侯溢出(虽然只有几个字节)就不能被测量下来。
总结
虽然局限性较大,ElectricFence的易用性一直是加分项。只要链接一次程序,ElectricFence就可以在检测出显存相关问题的时侯报案。不过,就像上面所说,ElectricFence须要配合像GDB这样的源码调试器使用。
评估版本:3.10.1
支持的Linux发行版:所有种类
许可:GPL
Valgrind[18]是一个提供好几款调试和剖析Linux程序性能的工具的套件。其实Valgrind能和不同语言——Java、Perl、Python、Assemblycode、ortran、Ada等——编写的程序一起工作,并且它主要还是针对使用C/C++所编撰的程序。
Memcheck,一款显存错误检查器,是其中最受欢迎的工具。它才能测量出如显存泄露、无效的显存访问、未定义变量的使用以及堆显存分配和释放相关的问题等众多问题。
更新内容
工具套件(3.10.1)[19]主要修补了3.10.0版本发觉的bug。除此之外,“从主干开发版本向后移植的一些补丁,修补了缺位的AArch64ARMv8指令和系统调用”。
有何优点
同其它所有Valgrind工具一样,Memcheck也是行程序。它的操作十分简单:一般我们会使用例如progarg1arg2格式的来运行程序,而Memcheck只要求你多加几个值即可,如valgrind--leak-check=fullprogarg1arg2。
Memcheck
(注意:由于Memcheck是Valgrind的默认工具,所以在行执行命令时无需提到Memcheck。并且,须要在编译程序之初带上-g参数选项,这一步会添加调试信息,致使Memcheck的错误信息会包含正确的行号。)
我真正倾心于Memcheck的是它提供了好多命令行选项(如上所述的--leak-check选项),这么除了能控制工具运转还可以控制它的输出。
举个事例,可以开启--track-origins选项,以查看程序源码中未初始化的数据;可以开启--show-mismatched-frees选项让Memcheck匹配显存的分配和释放技术。对于C语言所写的代码,Memcheck会确保只能使用free函数来释放显存,malloc函数来申请显存。而对C++所写的源码,Memcheck会检测是否使用了delete或delete操作符来释放显存,以及new或则new来申请显存。
Memcheck最好的特性,尤其是对于初学者来说,是它会给用户建议使用那个命令行选项能让输出愈加有意义。例如说,假如你不使用基本的--leak-check选项,Memcheck会在输出时给出建议:“使用--leak-check=full重新运行以查看更多泄露显存细节”。假如程序有未初始化的变量,Memcheck会形成信息:“使用--track-origins=yes以查看未初始化变量的定位”。
Memcheck另外一个有用的特点是它可以创建抑制文件suppressionfiles[20],由此可以略过特定的不能修正的错误,这样Memcheck运行时就不会每次都报案了。值得一提的是,Memcheck会去读取默认抑制文件来忽视系统库(例如C库)中的报错,这种错误在系统创建之前就早已存在了。可以选择创建一个新的抑制文件,或是编辑现有的文件(一般是/usr/lib/valgrind/default.supp)。
Memcheck还有中级功能,例如可以使用订制显存分配器[21]来测量显存错误[22]。除此之外,Memcheck提供监控命令[23],当用到Valgrind外置的gdbserver,以及顾客端恳求[24]机制(除了能把程序的行为告知Memcheck,还可以进行查询)时可以使用。
注意事项
毫无疑惑,Memcheck可以节约好多调试时间以及省去好多麻烦。并且它使用了好多显存,造成程序执行变慢(由文档可知[25],大约会耗费20至30倍时间)。
除此之外,Memcheck还有其它局限。依据用户评论,Memcheck很显著不是线程安全[26]的;它不能测量出静态缓冲区溢出[27];还有就是,一些Linux程序如GNUEmacs[28]目前还不能配合Memcheck工作。
假如有兴趣,可以在这儿[29]查看Valgrind局限性的详尽说明。
总结
无论是对于初学者还是这些须要中级特点的人来说,Memcheck都是一款方便的显存调试工具。假如你仅须要基本调试和错误检测,Memcheck会特别容易上手。而当你想要使用像抑制文件或则监控指令这样的特点,就须要花一些工夫学习了。
尽管列举了大量的局限性,而且Valgrind(包括Memcheck)在它的网站上宣称全球有成千上万程序员[30]使用了此工具。开发团队称收到来自超过30个国家的用户反馈,而这种用户的工程代码有的高达两千五百万行。
开发者:JohanLindh
评估版本:2.71
支持的Linux发行版:所有种类
许可:GNUGPL
Memwatch是由JohanLindh开发的显存调试工具,即使它饰演的主要角色是显存泄露检查器,而且(按照网页介绍)它也具有测量其它如显存重复释放和错误释放[32]、缓冲区溢出和下溢、野表针[33]写入等等显存相关问题的能力。
Memwatch支持用C语言所编撰的程序。也可以在C++程序中使用它,而且这些做法并不倡导(由Memwatch源码包随附的Q&A文件中可知)。
更新内容
这个版本添加了ULONG_LONG_MAX以分辨32位和64位程序。
有何优点
跟Dmalloc一样,Memwatch也有优秀的文档资料。参考USING文件,可以学习怎么使用Memwatch,可以了解Memwatch是怎样初始化、如何清除以及怎样进行I/O操作,等等。还有一个FAQ文件,借以帮助用户解决使用过程碰到的通常问题。最后还有一个test.c文件提供工作案例参考。
Memwatch
不同于Mtrace,Memwatch形成的日志文件(一般是memwatch.log)是人类可阅读的格式。并且,Memwatch每次运行时总会把显存调试结果拼接到输出该文件的末尾。这么便可在须要之时轻松查看之前的输出信息。
同样值得一提的是当你执行了启用Memwatch的程序,Memwatch会在标准输出[34]中形成一个单行输出,告知发觉了错误,之后你可以在日志文件中查看输出细节。假如没有形成错误信息,就可以确保日志文件不会写入任何错误,多次运行的话确实能节约时间。
另一个我喜欢的优点是Memwatch还提供了在源码中获取其输出信息的方法,你可以获取信息,之后任由你进行处理(参考Memwatch源码中的mwSetOutFunc()函数获取更多有关的信息)。
注意事项
跟Mtrace和Dmalloc一样,Memwatch也须要你往你的源文件里降低代码:你须要把memwatch.h这个头文件包含进你的代码。并且,编译程序的时侯,你须要连同memwatch.c一块编译;或则你可以把早已编译好的目标模块包含上去,之后在命令行定义MEMWATCH和MW_STDIO变量。不用说,想要在输出中定位行号,-g编译器选项也少不了。
据悉,Memwatch缺乏一些特点。例如Memwatch不能测量出对一块早已被释放的显存进行写入操作,或是在分配的显存块之外的进行读取操作。并且,Memwatch也不是线程安全的。还有一点,正如我在开始时强调,在C++程序上运行Memwatch的结果是不能预想的。
总结
Memcheck可以测量好多显存相关的问题,在处理C程序时是十分方便的调试工具。由于源码精巧,所以可以从中了解Memcheck怎样运转,有须要的话可以调试它,甚至可以按照自身需求扩充升级它的功能。
开发者:RolandMcGrath和UlrichDrepper
评估版本:2.21
Mtrace是GNUC库[36]中的一款显存调试工具,同时支持Linux上的C和C++程序,可以测量由函数malloc和free不匹配的调用所造成的显存泄露问题。
Mtrace
Mtrace实际上是实现了一个名为mtrace的函数,它可以跟踪程序中所有malloc/free调用,并在用户指定的文件中记录相关信息。文件以一种机器可读的格式记录数据,所以有一个Perl——同样命名为mtrace——用来把文件转换并为人类可读格式。
更新内容
Mtrace源码[37]和Perl文件[38]同GNUC库(2.21版本)一起释出,不仅更新版权日期,其它别无改动。
有何优点
Mtrace最好的地方是它十分简单易学。你只须要了解在你的源码中如何以及何处添加mtrace及对应的muntrace函数,还有怎样使用Mtrace的Perl。前者特别简单,只须要运行指令mtrace
(事例见开头截图最后一条指令)。
Mtrace另外一个优点是它的可伸缩性,这彰显在除了可以使用它来调试完整的程序,还可以使用它来检查程序中独立模块的显存泄露。只需在每位模块里调用mtrace和muntrace即可。
最后一点,由于Mtrace会在mtrace——在源码中添加的函数——执行时被触发,因而可以很灵活地使用讯号[39]动态地(在程序执行时)使能Mtrace。
注意事项
由于mtrace和mauntrace函数——声明在mcheck.h文件中,所以必须在源码中包含此头文件——的调用是Mtrace工作的基础(mauntrace()函数并非总是必要[40]),因而Mtrace要求程序员起码改动源码一次。
须要注意的是,在编译程序的时侯带上-g选项(GCC[41]和G++[42]编译器均有提供),能够使调试工具在输出结果时展示正确的行号。除此之外,有些程序(取决于源码容积有多大)可能会花很长时间进行编译。最后,带-g选项编译会降低了可执行文件的大小(由于提供了额外的调试信息)linux学习论坛,因而记得程序须要在测试结束后,不带-g选项重新进行编译。
使用Mtrace,你须要把握Linux环境变量的基本知识,由于在程序执行之前,须要把用户把环境变量MALLOC_TRACE的值设为指定的文件(mtrace()函数将会记录全部信息到其中)路径。
Mtrace在检查显存泄露和企图释放未经过分配的显存方面存在局限。它不能测量其它显存相关问题如非法显存访问、使用未初始化显存。并且linux修改环境变量 系统崩了,有人埋怨[43]Mtrace不是线程安全[44]的。
总结
不言自明,我在此讨论的每款显存调试器都有其优点和局限。所以,哪一款适宜你取决于你所须要的特点,尽管有时侯容易安装和使用也是一个决定诱因。
要想捕获软件程序中的显存泄露,Mtrace最适宜不过了。它还可以节约时间。因为Linux系统早已预装了此工具,对于不能联网或则不可以下载第三方调试调试工具的情况,Mtrace也是极有裨益的。
另一方面,相比Mtrace,Dmalloc除了能检查更多错误类型,还提供更多特点,例如运行时可配置、GDB集成。并且,Dmalloc不像这儿所说的其它工具,它是线程安全的。更不用说它的详尽资料了,这让Dmalloc成为初学者的理想选择。
尽管Memwatch的资料比Dmalloc的愈发丰富,并且能够测量更多的错误种类,并且你只能在C语言写就的程序中使用它。一个让Memwatch脱颖而出的特点是它容许在你的程序源码中处理它的输出,这对于想要订制输出格式来说是十分有用的。
假如改动程序源码非你所愿,这么使用ElectricFence吧。不过,请记住,ElectricFence只能测量两种错误类型,而此两者均非显存泄露。还有就是,须要基本了解GDB以最大化发挥这款显存调试工具的作用。
Memcheck可能是其中综合性最好的了。相比这儿提到的其它工具,它能检查更多的错误类型,提供更多的特点,但是不须要你的源码做任何改动。但请注意,基本功能并不难上手,而且想要使用它的中级特点,就必须学习相关的专业知识了。
作者:HimanshuArora[45]译者:soooogreen[46]校对:PurlingNayuki[47],ezio[48]
本文由LCTT[49]原创编译,Linux中国[50]荣誉推出
[1]:
[2]:
[3]:
[4]:
[5]:#Fence-Post%20Overruns
[11]:+source/electric-fence/2.2.3
[12]:#Dynamic_memory_allocation
[13]:
[14]:
[18]:
[27]:%28v=cs.20%29.aspx
[34]:#Standard_output_.28stdout.29
[36]:
[37]:;a=history;f=malloc/mtrace.c;h=df10128b872b4adc4086cf74e5d965c1c11d35d2;hb=HEAD
[38]:;a=history;f=malloc/mtrace.pl;h=0737890510e9837f26ebee2ba36c9058affb0bf1;hb=HEAD
[43]:
[44]:
[46]:
[47]:
[48]:
[49]:
[50]:
本文原创地址://gulass.cn/sdtszxcwbjhs.html编辑:刘遄,审核员:暂无