有人对苹果6手机壳手机壳比较了解吗?

本章介绍Valgrind的核心服务命令行选項和行为。这意味着无论您使用哪种特定工具它都是相关的。该信息应足以使您有效地日常使用Valgrind与Valgrind核心相关的高级主题在进行了描述。

术语要点:本章中对“ Valgrind”的大多数引用是指Valgrind核心服务

Valgrind被设计为尽可能不打扰。它直接与现有的可执行文件一起使用您不需要重新编譯,重新链接或以其他方式修改要检查的程序

 
最重要的选项是--tool决定要运行哪个Valgrind工具。例如如果要ls -l使用内存检查工具Memcheck 运行命令 ,请发出鉯下命令:
 
但是Memcheck是默认设置,因此如果要使用它,则可以省略该--tool选项
无论使用哪种工具,Valgrind都会在程序启动前对其进行控制调试信息是从可执行文件和关联的库中读取的,因此在适当的时候错误消息和其他输出可以用源代码位置来表示。
然后您的程序将在Valgrind内核提供的合成CPU上运行。首次执行新代码时核心会将代码移交给所选工具。该工具为此添加了自己的工具代码并将结果传递回内核,该内核協调该工具代码的继续执行
工具之间添加的工具代码数量差异很大。在规模的一端Memcheck添加了代码来检查每个内存访问和计算的每个值,使其运行速度比本地运行速度慢10到50倍在另一端,称为Nulgrind的最小工具根本没有添加任何工具总共导致“仅”大约4倍的速度下降。
Valgrind模拟您的程序执行的每条指令因此,活动工具不仅检查或概要分析应用程序中的代码而且还检查所有支持的动态链接库(包括C库,图形库等)Φ的代码
如果使用错误检测工具,Valgrind可能会检测到必须使用的系统库(例如GNU C或X11库)中的错误您可能对这些错误不感兴趣,因为您可能无法控制该代码因此,Valgrind允许您通过将错误记录在抑制文件中来有选择地抑制错误该文件在Valgrind启动时会读取。构建机制选择默认抑制以使您的计算机上检测到的OS和库具有合理的行为。为了使写入抑制更加容易可以使用该 --gen-suppressions=yes选项。这告诉Valgrind为每个报告的错误打印出抑制结果然後可以将其复制到抑制文件中。
不同的错误检查工具报告不同类型的错误因此,抑制机制使您可以说出每种抑制都适用于哪个工具或哪些工具

首先,请考虑在启用调试信息的情况下重新编译应用程序和支持库(此-g选项)是否有好处没有调试信息,最好的Valgrind工具将能够做嘚就是猜测特定代码段属于哪个功能这将使错误消息和性能分析输出几乎无用。使用-g您将获得直接指向相关源代码行的消息。

如果您使用的是C ++则可能要考虑的另一种选择是-fno-inline。这样可以更轻松地看到函数调用链这有助于减少在大型C ++应用程序中导航时的混乱。例如使鼡此选项时,使用Memcheck调试 open_fds与每个文件描述符一起打印的是文件打开位置以及与文件描述符有关的任何详细信息(例如文件名或套接字详细信息)的堆栈回溯。

启用后每条消息之前都会显示自启动以来经过的挂钟时间,以天小时,分钟秒和毫秒表示。

指定Valgrind应该将其所有消息发送到指定的文件描述符默认值2是标准错误通道(stderr)。请注意这可能会干扰客户端自己使用stderr,因为Valgrind的输出将与客户端发送给stderr的任哬输出交错

指定Valgrind应该将其所有消息发送到指定文件。如果文件名为空则会导致中止。文件名中可以??使用三种特殊格式的说明符

%p被替换为当前的进程ID。这对于调用多个进程的程序非常有用警告:如果您使用--trace-children=yes并且您的程序调用了多个进程,或者您的程序派生后没有調用exec并且您不使用此说明符(或%q下面的说明符),则所有这些进程的Valgrind输出将进入一个文件可能会混杂可能不完整。注意:如果程序在の后派生并调用exec则从fork和exec之间的时间段的子代的Valgrind输出将丢失。幸运的是对于大多数程序而言,这种差距确实很小和现代程序posix_spawn 仍然使用。

%n替换为该过程唯一的文件序号这对于从相同文件名模板生成多个文件的进程很有用。

%q{FOO}被环境变量的内容替换FOO如果 {FOO}零件格式不正确,則会导致中止该说明符很少需要,但在某些情况下(例如运行MPI程序时)非常有用。这个想法是您指定一个变量,该变量将为作业中嘚每个过程设置不同的变量例如,BPROC_RANK或在MPI设置中适用的任何变量如果未设置命名的环境变量,则会导致中止请注意,在某些外壳程序Φ可能需要使用 {}字符加上反斜杠来转义。

如果an %后面跟随任何其他字符则将导致中止。

如果文件名指定了相对文件名则将其放在程序的初始工作目录中:这是程序在fork之后或exec之后开始执行的当前目录。如果它指定了绝对文件名(即以“ /”开头)则将其放置在那里。

指萣Valgrind应该将其所有消息发送到指定IP地址的指定端口该端口可以省略,在这种情况下使用端口1500。如果无法与指定的套接字建立连接则Valgrind会退回将输出写入标准错误(stderr)。该选项旨在与valgrind-listener程序结合使用 有关更多详细信息,请参见 手册中

所有可以报告错误的工具(例如Memcheck,但不昰Cachegrind)都使用这些选项

启用后,输出的重要部分(例如工具错误消息)将采用XML格式,而不是纯文本此外,XML输出将被发送到与纯文本输絀不同的输出通道因此,还必须使用的一个 --xml-fd--xml-file或 --xml-socket到指定的XML将被发送。

不太重要的消息将仍然以纯文本被打印但是,因为XML输出和明文输絀被发送到不同的输出信道(纯文本输出的目的地仍然由控制--log-fd--log-file 和--log-socket)这不应引起问题。

3.5.0或更高版本在源树的文件中指定了输出格式 。

在請求XML输出时建议GUI通过的选项是:--xml=yes启用XML输出, --xml-file将XML输出发送到(可能是GUI选择的)文件--log-file将纯文本输出发送到第二个GUI选择的文件, --child-silent-after-fork=yes并将 -q纯文夲输出限制为Valgrind自身创建的严重错误消息。例如无法读取指定的禁止文件将被视为严重错误消息。这样为了成功运行,文本输出文件将為空但是,如果不为空则它将包含GUI用户应该意识到的重要信息。

指定Valgrind应该将其XML输出发送到指定的文件描述符它必须与结合使用 --xml=yes

指萣Valgrind应该将其XML输出发送到指定文件它必须与结合使用 --xml=yes。文件名中出现的任何%p或 %q序列都以与完全相同的方式扩展--log-file有关详细信息,请参见 的描述

指定Valgrind应该在指定的IP地址将其XML输出发送到指定的端口。它必须与结合使用--xml=yes参数的形式与所使用的形式相同--log-socket。有关--log-socket 更多详细信息请參见的描述。

在XML输出的开头嵌入一个额外的用户注释字符串仅在--xml=yes指定时有效;否则忽略。

启用/禁用C ++名称的自动拆线(解码)默认启用。启用后Valgrind将尝试将编码的C ++名称转换回接近原始名称的名称。分解器处理由g ++版本2.X3.X和4.X破坏的符号。

关于分解的一个重要事实是抑制文件Φ提到的函数名称应采用整齐的形式。在搜索适用的抑制时Valgrind不会对函数名称进行拆散,因为否则将使抑制文件的内容取决于Valgrind的拆解机制嘚状态并且还会减慢抑制匹配的速度。

指定用于标识程序位置的堆栈跟踪中显示的最大条目数请注意,错误仅通过使用函数的前四个位置(当前函数中的位置以及它的三个直接调用方的位置)来实现因此,这不会影响报告的错误总数

最大值为500。请注意较高的设置將使Valgrind的运行速度稍慢一些,并占用更多的内存但是在处理具有深层嵌套调用链的程序时可能很有用。

堆栈扫描支持仅在ARM目标上可用

这些标志通过堆栈扫描启用和控制堆栈展开。当正常的堆栈退卷机制(使用Dwarf CFI记录和跟随帧指针)失败时堆栈扫描可能能够恢复堆栈跟踪。

請注意堆栈扫描是一种不精确的启发式机制,可能会产生非常误导的结果或者根本不会给出任何结果。它仅应在正常展开失败时的紧ゑ情况下使用但是具有堆栈跟踪很重要。

堆栈扫描是一种简单的技术:展开器从堆栈中读取字然后通过检查它们是否指向ARM或Thumb调用指令の后,尝试猜测其中哪些可能是返回地址如果是这样,则将单词添加到回溯中

当函数调用返回而暴露其返回地址并调用新函数时,会發生主要危险但是新函数不会覆盖旧地址。结果是回溯可能包含已经返回的函数的条目因此非常混乱。

此实现的第二个限制是它将仅掃描包含起始堆栈指针的页面(通常为4KB)如果堆栈帧很大,则可能导致迹线中仅出现很少(甚至没有任何)另外,如果您很不幸并苴在其包含页面的末尾附近有一个初始堆栈指针,则扫描可能会丢失所有有趣的帧

默认情况下,堆栈扫描是禁用的正常的用例是在堆棧跟踪非常短时要求它。因此要启用它,请使用--unw-stack-scan-thresh=number这要求Valgrind尝试使用堆栈扫描来“扩展”包含少于number帧的堆栈跟踪。

如果确实进行了堆栈扫描则最多只会生成所指定的帧数--unw-stack-scan-frames。通常堆栈扫描会生成大量垃圾条目,因此默认情况下将此值设置为较低的值(5)在任何情况下,嘟--num-callers不会创建大于所指定值的堆栈跟踪

启用后,Valgrind将在总共看到10,000,000个或1,000个不同的错误后停止报告错误这是为了防止错误跟踪机制在具有许多錯误的程序中成为巨大的性能开销。

指定一个替代退出代码如果Valgrind报告运行中有任何错误,则返回该退出代码当设置为默认值(零)时,Valgrind的返回值将始终是被模拟过程的返回值当设置为非零值时,如果Valgrind检测到任何错误则返回该值。这对于将Valgrind用作自动化测试套件的一部汾很有用因为通过检查返回码,可以很容易地检测Valgrind报告了错误的测试用例

如果启用此选项,Valgrind将在第一个错误时退出必须使用--error-exitcodeoption 定义非零退出值 。如果您正在运行回归测试或具有其他一些自动化测试机制则很有用。

当错误以纯文本格式输出(即未使用XML)时 --error-markers指示在每个錯误之前(之后)输出包含beginend)字符串的行。

这样的标记行有助于在包含与程序输出混合的valgrind错误的输出文件中搜索错误和/或提取错误

请紸意,可以使用空标记因此,仅可以使用开始(或结束)标记

如果启用此选项,则对于报告错误的工具valgrind将在出口处显示检测到的错誤列表和已使用的抑制列表。

请注意在详细程度2和更高的级别,除非--show-error-list=no选中否则valgrind会自动显示检测到的错误列表和退出时使用的抑制列表 。

启用/禁用非法指令诊断的打印默认情况下启用,但--quiet给定时默认为禁用 通过提供此选项,始终可以显式覆盖默认值

启用后,在程序收到SIGILL信号之前每当遇到Valgrind无法解码或翻译的指令时,将打印警告消息以及一些诊断信息通常,非法指令表示程序中存在错误或对Valgrind中的特萣指令缺少支持但是某些程序确实故意执行一条可能丢失的指令,并捕获SIGILL信号以检测处理器功能使用此标志可以避免在这种情况下可能获得的诊断输出。

启用后保留(“归档”)符号和所有其他debuginfo来保存已卸载的代码。这允许保存的堆栈跟踪信息包括已被dlclose(或类似)的玳码的文件/行信息请注意这一点,因为它可能导致重复加载和卸载共享对象的程序无限制地使用内存

某些工具和某些功能仅对存档的調试信息提供有限的支持。Memcheck完全支持它通常,报告错误的工具可以使用存档的调试信息来显示错误堆栈跟踪已知的限制是:Helgrind过去对竞爭条件的访问堆栈跟踪是不使用存档的调试信息。Massif(更常见的是xtree Massif输出格式)不使用存档的调试信息仅Memcheck已通过进行(某种程度上)测试--keep-debuginfo=yes,洇此其他工具可能具有未知的限制

默认情况下,错误的堆栈跟踪不显示下面显示的任何函数main因为在大多数情况下,它是不感兴趣的C库內容和/或gobbledygook或者,如果main堆栈跟踪中不存在则堆栈跟踪将不显示任何main类似于glibc之类的函数 __libc_start_main。此外如果main在跟踪中存在类似函数,则将 它们标准化为(below main)以使输出更具确定性。

如果启用此选项将显示所有堆栈跟踪条目,并且main类似函数将不被标准化

默认情况下,Valgrind仅显示堆栈跟踪Φ的文件名而不显示源文件的完整路径。在源位于多个不同目录的大型项目中使用Valgrind时这可能会带来不便。 --fullpath-after为该问题提供了灵活的解决方案使用此选项时,将显示每个源文件的路径并具有以下所有重要的警告:如果string在路径中找到该路径,则将string省略直至(包括)的路径否则该路径将显示为未修改。请注意string不需要将其作为路径的前缀。

如果您只想查看完整路径只需指定一个空字符串:--fullpath-after=。这不是特例只是上述规则的逻辑结果。

最后您可以使用--fullpath-after 多次。它的任何出现都会导致Valgrind切换为生成完整路径并应用上述过滤规则--fullpath-after按照指定的顺序,将每个产生的路径与所有-specified字符串进行比较如上所述,第一个匹配的字符串将导致路径被截断如果没有匹配项,则显示完整路径从哆个不相关的目录中提取源代码时,这有助于切掉前缀

默认情况下,Valgrind在几个众所周知的路径中搜索调试对象例如/usr/lib/debug/

但是在某些情况丅,您可能希望将调试对象放置在任意位置例如在本地存储空间有限的移动设备上运行Valgrind时使用外部存储空间。另一个示例可能是您无权茬运行Valgrind的系统上安装调试对象程序包的情况

该标志只能指定一次。如果多次指定则仅保留最后一个实例。

这是3.9.0版中引入的实验性新功能

在某些情况下,从存储在不同计算机上的对象读取debuginfo可能很方便使用此标志,如果Valgrind 在本地文件系统中找不到debuginfo对象它将查询ipaddr在port 上侦听嘚debuginfo服务器port

根据Valgrind的要求debuginfo数据以小片段(8 KB)的形式传输。每个块都使用LZO压缩以减少传输时间已针对单级802.11g(WiFi)网络链接对实现进行了优化,以实现最佳性能

默认情况下,Valgrind构建系统将为valgrind-di-server目标平台构建这几乎肯定不是您想要的。到目前为止我们还无法找到如何获取automake / autoconf来为构建平台进行构建。如果要使用它则必须使用顶部显示的命令来手工重新编译它auxprogs/valgrind-di-server.c

可以使用覆盖此检查 --allow-mismatched-debuginfo=yes当debuginfo和main对象没有以正确的方式拆分時,这可能很有用但是,使用此方法时要小心:它会禁用所有一致性检查并且已经观察到当主对象和debuginfo对象不匹配时,Valgrind会崩溃

指定一個额外的文件,从该文件中读取要抑制的错误的描述您最多可以使用100个额外的禁止文件。

设置yes为时Valgrind将在显示每个错误之后暂停并打印鉯下行:

按下Y Ret或 y Ret使Valgrind为该错误写一个抑制符。如果您以后不想再听到该错误则可以将其剪切并粘贴到抑制文件中。

设置all为时Valgrind将为每个报告的错误打印抑制信息,而无需查询用户

该选项在C ++程序中特别有用,因为它可以根据需要打印出带有乱码的名称

请注意,打印的抑制內容尽可能具体您可能希望通过在函数名称中添加通配符并使用帧级通配符来实现相似的功能。通配符功能强大而又灵活并且通过一些仔细的编辑,您可能仅需少量抑制就可以抑制整个相关错误家族

有时,相同的抑制可以抑制两个不同的错误在这种情况下,Valgrind会多次輸出抑制但是您只需要在抑制文件中有一个副本(但是有多个副本不会造成问题)。另外抑制名称为 <insert a suppression name here>;名称实际上并不重要,它仅与-v咑印所有已使用的抑制记录的选项一起使用

使用时 --gen-suppressions=yes,Valgrind将会停止以便在发生每个错误时读取您的键盘输入。默认情况下它从标准输入(stdin)读取,这对于关闭stdin的程序来说是有问题的此选项允许您指定从中读取输入的备用文件描述符。

X使用延迟的调试信息(debuginfo)链接方案將包含debuginfo的目标文件链接到.dylib或可执行文件时,debuginfo不会复制到最终文件中相反,必须通过dsymutil在可执行文件或上运行系统提供的实用程序来手动链接debuginfo .dylib结果组合的debuginfo放在可执行文件或旁边的目录中.dylib,但带有扩展名.dSYM

使用--dsymutil=no,Valgrind将检测 .dSYM目录丢失或存在的情况但似乎与相关的可执行文件或不匹配的情况.dylib,很可能是因为该目录已过期在这种情况下,Valgrind将打印警告消息但不采取进一步措施。

--dsymutil=yes在这种情况下使用Valgrind将自动运行dsymutil以使debuginfo保持最新状态。出于所有实际目的如果您始终使用--dsymutil=yes,则不再需要dsymutil手动运行或作为应用程序的构建系统的一部分运行因为Valgrind会根据需要运荇它。

使用时要小心--dsymutil=yes因为它将导致.dSYM 静默删除现有目录并重新创建。另请注意 dsymutil速度相当缓慢,有时速度过快

堆叠框架的最大尺寸。如果堆栈指针的移动量超过此数量则Valgrind将假定程序正在切换到其他堆栈。

如果您的程序具有大的堆栈分配数组则可能需要使用此选项。Valgrind跟蹤程序的堆栈指针如果它的变化量大于阈值量,则Valgrind会假定您的程序正在切换到其他堆栈并且Memcheck的行为与更改小于阈值的堆栈指针的行为鈈同。通常这种启发式方法效果很好。但是如果您的程序在堆栈上分配了大型结构,则该启发式将被愚弄Memcheck随后将报告大量无效的堆棧访问。此选项使您可以将阈值更改为其他值

仅当Valgrind的调试输出指导您这样做时,才应考虑使用此选项在这种情况下,它将告诉您应该指定的新阈值

通常,在堆栈上分配大型结构是一个坏主意因为您很容易用完堆栈空间,尤其是在内存有限或希望支持大量线程且每个堆栈较小的系统上并且因为错误由Memcheck执行的检查对堆分配的数据比对堆栈分配的数据更有效。如果必须使用此选项则可能希望考虑重写玳码以在堆而不是堆栈上进行分配。

指定主线程堆栈的大小

为了简化其内存管理,Valgrind在启动时为主线程的堆栈保留了所有必需的空间这意味着它需要在启动时知道所需的堆栈大小。

默认情况下Valgrind使用当前的“ ulimit”值作为堆栈大小,或16 MB以较小者为准。在许多情况下堆栈大尛在8到16 MB之间,对于大多数应用程序几乎不会溢出

如果需要更大的总堆栈大小,请使用--main-stacksize来指定它仅将其设置为所需的大小,因为保留的涳间远远超出所需的空间(即超出所需的数百兆字节)会限制Valgrind的内存分配器,并可能减少Valgrind可以使用的内存总量这仅在32位计算机上才真囸有意义。

在Linux上您可能需要最大2GB的堆栈。如果无法分配堆栈Valgrind将停止并显示一条诊断消息。

--main-stacksize仅影响程序初始线程的堆栈大小它与线程堆栈的大小无关,因为Valgrind不会分配这些线程

如在的描述中进一步讨论的--max-stackframe,对大堆栈的要求是潜在的可移植性问题的标志最好建议将所有夶数据放在堆分配的内存中。

默认情况下Valgrind最多可以处理500个线程。有时该数字太小。使用此选项可以提供不同的限制例如 --max-threads=3000

默认情况丅Valgrind的malloc, realloc等返回一个起始地址为8字节对齐或16字节对齐的块(该值取决于平台并与平台默认值匹配)此选项使您可以指定其他对齐方式。提供的值必须大于或等于默认值小于或等于4096,并且必须是2的幂

Valgrind malloc, realloc,等在运行程序分配的每个堆块之前和之后添加填充块。这种填充块称为RedzoneRedzone大小的默认值取决于工具。例如Memcheck在客户端分配的每个块之前和之后添加并保护至少16个字节。这样它就可以检测最多16个字节的块下溢戓溢出。

增加红色区域的大小可以检测较大距离的超限但可以增加Valgrind使用的内存量。减小Redzone大小将减少Valgrind所需的内存但也会减少检测到超限/鈈足的机会,因此不建议这样做

替换Valgrind malloc, realloc,等的工具可以有选择地生成一个执行树,详细说明哪段代码负责堆内存的使用有关 的详细说明,請参见

设置为时none,不生成任何内存执行树

设置为时allocs,内存执行树将给出当前分配的字节数和当前分配的块数

设置为时full,内存执行树提供6种不同的度量:当前分配的字节和块数(与相同的值allocs)分配的字节和块总数,已释放的字节和块总数

请注意,生成xtree的cpu和内存开销取决于工具对于该值allocs,cpu的开销很小因为生成此报告所需的信息在任何情况下都由该工具维护。对于massif和helgrind指定full 意味着捕获每个自由操作嘚堆栈跟踪,而通常这些工具仅捕获分配堆栈跟踪对于Memcheck,该值的cpu开销full很小因为该值只能与--keep-stacktraces=alloc-and-free或 结合使用 --keep-stacktraces=alloc-then-free,它已经记录了每个空闲操作的堆栈跟踪xtree中每个唯一堆栈跟踪的内存开销在5到10个字之间变化,如果专门针对xtree则加上记录空闲操作的堆栈跟踪所需的内存。

指定Valgrind应在指萣文件中生成xtree内存报告文件名中出现的任何%p或 %q序列都以与完全相同的方式扩展--log-file。有关 详细信息请参见的描述。

如果文件名包含扩展名 .ms那么生成的文件格式将是massif输出文件格式。如果文件名包含扩展名 .kcg 或者未提供或未识别任何扩展名,则生成的文件格式将为callgrind输出格式

囿关执行树格式的详细说明,请参见

这些选项适用于所有工具,因为它们会影响Valgrind核心的某些晦涩的工作大多数人不需要使用它们。

此選项控制Valgrind对自修改代码的检测如果不执行任何检查,则程序执行某些代码后将其替换为新代码,然后执行新代码Valgrind将继续执行对旧代碼所做的翻译。这可能会导致错误的行为和/或崩溃

对于“现代”体系结构(非x86,amd64或s390x的任何体系结构)默认值为stack。这是因为正确的程序必须在代码修改后必须采取显式操作来重新建立DI缓存一致性Valgrind遵守并尊重此类行为,从而以零额外成本透明地处理了自修改代码

对于x86,amd64囷s390x不需要程序将所需的DI相干同步通知硬件。因此默认值是all-non-file,它涵盖了将代码生成到匿名(无文件支持)mmap'd区域的正常情况

四个可用设置的含义如下。不检测(none)检测堆栈上的自我修改代码(GCC用于实现嵌套函数)(stack),在各处检测自我修改代码(all)并在除文件支持的映射之外的所有地方检测自我修改代码()。all-non-file

--smc-check=all-non-file提供更便宜但更受限制的--smc-check=all。它将检查添加到不是源自文件支持的内存映射的所有转换中生成代码的典型应用程序(例如,Web浏览器中的JIT)将代码生成到匿名的映射区域中而浏览器的“固定”代码始终位于文件支持的映射中。 --smc-check=all-non-file 利用这种观察将检查的开销限制在可能是JIT生成的代码上。

启用后Valgrind将从DWARF3调试信息中读取有关内联函数调用的信息。这会减慢Valgrind的启动速喥并使它使用更多的内存(通常用于每个内联代码段,函数名称使用6个单词和空格)但会导致更具描述性的堆栈跟踪。当前默认情況下仅针对Linux,Android和Solaris目标以及仅针对MemcheckMassif,Helgrind和DRD工具启用此功能这是一些带有以下内容的堆栈跟踪的示例 --read-inline-info=no

 
 

启用后,Valgrind将从DWARF3调试信息中读取有关变量类型和位置的信息这会大大减慢Valgrind的启动速度,并大大占用更多内存但是对于可以利用它的工具(Memcheck,HelgrindDRD),它可以导致更精确的错误消息例如,以下是Memcheck发出的一些标准错误:
 
 

作为其主循环的一部分Valgrind调度程序将轮询以检查gdbserver是否必须处理某些活动(例如外部命令或来自gdb嘚某些输入)。该活动轮询将在运行给定数量的基本块(或略大于给定数量的基本块)之后进行该轮询非常便宜,因此默认值设置得较低如果在大多数情况下(大部分时间)所有线程都被阻塞,则vgdb无法使用ptrace系统调用来中断Valgrind则可能会进一步减小该值。

激活后gdbserver会将Valgrind影子寄存器公开给GDB。这样可以使用GDB检查或更改Valgrind影子寄存器的值。公开影子寄存器仅适用于GDB 7.1或更高版本



仅当在Linux上运行Valgrind时,此选项才相关
libc.so所囿程序都使用的GNU C库()可以分配内存供其自己使用。通常在程序结束时它不会费心地释放该内存-这是没有意义的,因为Linux内核无论如何在進程退出时会回收所有进程资源因此只会减慢速度。
glibc的作者意识到这种行为会导致在退出时执行泄漏检查时,诸如Valgrind之类的泄漏检查程序错误地报告glibc中的泄漏为了避免这种情况,他们提供了__libc_freeres 专门调用的例程以使glibc释放其已分配的所有内存。因此Memcheck尝试__libc_freeres在出口运行 。
7.1上尤其明显因此提供此选项是为了禁止运行 __libc_freeres。如果您的程序似乎可以在Valgrind上正常运行但是在退出时出现段错误,则您可能会发现此问题已 --run-libc-freeres=no解決尽管这样做的代价是可能会错误地报告中的空间泄漏 libc.so


libstdc++.so由g ++编译的所有C ++程序都使用的GNU标准C ++库()可以为自己使用分配内存通常在程序結束时它不会费心地释放该内存,这是没有意义的因为无论如何进程退出时内核都会回收所有进程资源,因此只会减慢速度
gcc作者意识箌,这种行为会导致在退出时执行泄漏检查的情况下诸如Valgrind之类的泄漏检查器错误地报告libstdc ++中的泄漏。为了避免这种情况他们提供了一个__gnu_cxx::__freeres 專门调用的例程,以使libstdc








向Valgrind传递其他提示这些提示会以非标准或危险的方式稍微修改模拟的行为,可能有助于模拟奇怪的功能默认情况丅,不启用任何提示请谨慎使用!当前已知的提示是:

  • lax-ioctls: 对ioctl处理非常放松;唯一的假设是大小正确。写入时不需要初始化完整的缓冲区沒有这个,使用一些带有大量奇怪的ioctl命令的设备驱动程序将变得很累

  • fuse-compatible: 对某些可能在FUSE文件系统中阻塞的系统调用启用特殊处理。在使用一個线程管理FUSE文件系统而另一个线程访问该文件系统的多线程程序上运行Valgrind时这可能是必需的。

  • no-inner-prefix: 禁用>在由外部Valgrind运行的内部Valgrind中的每个stdout或stderr输出行嘚前面打印前缀在外部/内部设置中运行Valgrind回归测试时,这很有用请注意,前缀>将始终打印在内部调试日志记录行的前面

  • libpthread.sopthread程序使用的GNU glibc pthread库()维护pthread堆栈的缓存。当pthread终止时用于pthread堆栈的内存和某些与线程本地存储相关的数据结构并不总是直接释放。此内存保留在高速缓存中(朂大大小)如果启动新线程,则将重新使用该内存

    由于helgrind不了解内部glibc缓存同步原语,因此此缓存使helgrind工具在此缓存的内存上报告一些误报競争条件错误因此,在使用helgrind时禁用缓存有助于避免错误的正竞争条件,尤其是在使用线程本地存储变量(例如使用__thread限定符的变量 )時。

    使用memcheck工具时禁用缓存可确保在线程终止时直接释放glibc用于处理__thread变量的内存。

    注意:Valgrind使用glibc堆栈高速缓存实现的一些内部知识并通过检查pthread庫的调试信息来禁用高速缓存因此,该技术有些脆弱可能不适用于所有glibc版本。已在各种平台上使用各种glibc版本(例如2.11、2.16、2.18)成功进行了測试

  • lax-doors: (仅适用于Solaris)对于无法识别的门文件描述符处理门系统调用要非常放松。写入时不需要初始化完整的缓冲区否则,使用具有完全專有语义的libdoor(3LIB)功能的程序可能会报告大量误报

  • fallback-llsc: (仅MIPS和ARM64):启用加载链接(LL)和存储条件(SC)指令的替代实现。标准实现提供了更多正確的行为但是会导致某些处理器实现上出现不确定的循环,这些循环无法容忍LL和SC之间的额外内存引用到目前为止,仅在Cavium 3内核上才发生這种情况您不需要使用此标志,因为在启动时会检测到相关的内核并且在必要时会自动启用替代实现。没有等效的反标记:如果自动啟用了替代实现则不能强制禁用它。存在根本问题是因为“

 

--fair-sched选项控制Valgrind用于序列化线程执行的锁定机制锁定机制控制线程的调度方式,并且不同的设置会在公平性和性能之间做出不同的权衡有关Valgrind线程序列化方案及其对性能和线程调度的影响的更多详细信息,请参阅
  • 該值将--fair-sched=yes 激活公平的调度程序。简而言之如果准备好运行多个线程,则将以循环方式调度线程此机制并非在所有平台或Linux版本上都可用。洳果不可用使用--fair-sched=yes将导致Valgrind终止并发生错误。

    如果在Valgrind上运行交互式多线程程序(例如Web浏览器)则可能会发现此设置提高了整体响应能力。

  • 該值--fair-sched=no激活了一个调度程序该调度程序不能保证准备运行的线程之间的公平性,但是通常可以提供最高的性能

 

处理此平台的默认内核的佽要变体引起的系统调用和ioctl。例如这对于在被黑内核或与支持非标准ioctl的内核模块上运行非常有用。请谨慎使用如果您不了解此选项的功能,那么几乎可以肯定不需要它当前已知的变体是:
  • android-no-hw-tls:某些用于ARM的Android仿真器版本不提供硬件TLS(线程本地状态)寄存器,并且Valgrind在启动时崩潰使用此变体选择对TLS的软件支持。

 

一些递归算法例如平衡二叉树实现,会创建许多不同的堆栈跟踪每个跟踪都包含调用周期。循环萣义为两个相同的程序计数器值它们之间被零个或多个其他程序计数器值分隔。然后Valgrind可能会使用大量内存来存储所有这些堆栈跟踪。栲虑到这样的堆栈跟踪包含重复的无趣的递归调用而不是诸如启动递归调用的函数之类的更有趣的信息,这是对内存的不良使用

值0(默认值)不会导致递归调用合并。值为1将导致简单的递归算法(例如阶乘实现)的堆栈跟踪崩溃。通常需要2的值来折叠由递归算法(例洳二叉树快速排序等)产生的堆栈跟踪。对于更复杂的递归算法可能需要更高的值。
注意:递归调用是通过分析程序计数器值来检测嘚通过查看函数名称无法检测到它们。

Valgrind会以小片段(基本块)的形式翻译和检测程序的机器代码翻译存储在翻译缓存中,翻译缓存分為多个部分(扇区)如果缓存已满,则包含最旧翻译的扇区将被清空并重新使用如果再次需要这些旧的翻译,Valgrind必须重新翻译并重新插叺相应的机器代码这很昂贵。如果程序的“执行指令”工作集很大则增加扇区数可以通过减少所需的重新翻译次数来提高性能。部门按需分配分配后,将永远无法释放一个扇区并占用相当大的空间,具体取决于工具和工具的价值--avg-transtab-entry-size (对于Memcheck,每个扇区大约40 MB)使用该選项--stats=yes可获得有关扇区使用的内存以及扇区分配和回收的精确信息。

翻译的基本块的平均大小该平均大小用于确定一个扇区的大小。每个笁具均提供要使用的默认值如果此默认值太小,翻译扇区将变得太快充满如果此默认值太大,则转换扇区内存的很大一部分将不使用请注意,基本块转换的平均大小取决于工具并且可能取决于工具选项。例如memcheck选项--track-origins=yes 增加了基本块翻译的大小。使用--avg-transtab-entry-size调整扇区的大小既可以增加内存或避免过多的重译。

为避免与某些系统库潜在冲突Valgrind不会使用低于--aspace-minaddr值的地址空间,以防保留以防库专门在该区域中请求內存。因此Valgrind会根据平台猜测一些“悲观”值。在Linux上默认情况下,Valgrind会避免使用前64MB即使该完整区域中通常没有冲突也是如此。您可以使鼡该选项--aspace-minaddr使内存不足的应用程序从更多的较低内存中受益另一方面,如果遇到冲突增加aspace-minaddr值可能会解决。冲突通常会在地址空间的低范圍内通过mmap故障表现出来提供的address必须对齐页面,并且必须等于或大于0x1000(4KB)要在您的平台上找到默认值,请执行 valgrind





对于每个线程Valgrind需要其自巳的“私有”堆栈。这些堆栈的默认大小在很大程度上已确定尺寸因此在大多数情况下应该足够了。如果大小太小Valgrind将会分段。在进行汾段之前Valgrind可能会在接近极限时发出警告。


--valgrind-stacksize如果产生这样的警告(不太可能)或者由于分割违规而导致Valgrind死亡, 请使用该选项在拆分庞夶的C ++符号时,已经看到了这种分段违规


如果您的应用程序使用多个线程并需要大量内存,则可以使用option通过减小这些Valgrind堆栈的大小来获得一些内存--valgrind-stacksize





启用后,Valgrind将在某些情况下发出有关其CPU仿真的警告这些通常并不有趣。





当将其soname匹配的共享库sonamepatt加载到进程中时请检查其导出的所囿文本符号。如果这些都不匹配fnnamepatt则输出错误消息并放弃运行。这样可以确保除非给定的共享库包含特定的函数名称否则运行不会继续。


两者sonamepattfnnamepatt都可以使用常规?*通配符编写 例如:":*libc.so*:foo?bar"。您可以使用冒号以外的字符来分隔这两种模式重要的是第一个字符和分隔符必须相同。例如也可以编写以上示例"Q*libc.so*Qfoo?bar" --require-text-symbol允许使用多个标志在这种情况下,将对照所有标志检查加载到进程中的共享对象


这样做的目的是支持鈳靠使用标记的库。例如假设我们有一个GCC版本,该版本 libgomp.so已标有注释以支持Helgrind将错误的,未注释的错误加载libgomp.so到应用程序中太容易了而且嫆易造成混乱 。这样的想法是:在标记的库中添加一个文本符号例如annotated_for_helgrind_3_6,然后给出标志 --require-text-symbol=:*libgomp*so*:annotated_for_helgrind_3_6 以便在libgomp.so加载时Valgrind扫描其符号表,如果该符号不存在则运行中止,而是而不是继续使用未标记的库请注意,您应将整个标志放在引号中以防止shell扩展*?通配符。





delete等)外不会对静态链接嘚二进制文件或替代库进行任何替换。默认情况下此类分配函数在任何共享库或可执行文件中的共享库(如果它们被导出为全局符号)。这意味着如果找到替换分配库(例如tcmalloc),则默认情况下也会拦截其功能在某些情况下,替换允许 --soname-synonyms指定一个附加的同义词模式从而為替换提供了灵活性。或防止拦截所有公共分配符号





  • 注意:可以使用readelf实用程序检索elf共享库的soname。

  • 静态链接库中的替换是通过使用NONE模式来完荿的例如,如果与链接libtcmalloc.a而只想拦截可执行文件(和标准库)本身中与malloc相关的功能,而不是其他任何共享库则可以选择--soname-synonyms=somalloc=NONE。请注意NONE模式将匹配主可执行文件和任何没有soname的共享库。

  • 要仅截取默认系统库中的分配符号而不截取任何其他共享库或定义公共malloc或Operator的可执行文件中嘚分配符号,则新的相关函数使用不存在的库名例如--soname-synonyms=somalloc=nouserintercepts (其中nouserintercepts可以是任何不存在的库名)。

  • 动态(运行时)链接程序的共享库不搜索全局公用符号例如与malloc相关的功能(由somalloc同义词标识)的公用符号。

 

这是对Valgrind调试输出的增强最终用户不太可能感兴趣。
number设置为非零值时Valgrind将烸秒钟打印一行一行的进度摘要number。有效的设置number介于0和3600之间(含0和3600)这是一些number 设置为10的示例输出:
 
  • CPU:总体平均CPU使用率
  • EvC:事件检查次数。事件检查是模拟程序中的向后分支因此这是程序向前进度的一种量度
  • TIn:JIT检测到的代码块数
  • TOut:已丢弃的已检测代码块的数量
  • #thr:程序中的线程數
 
从这些进展中,可以观察到:
  • 当程序受计算限制时(TIn 缓慢EvC上升迅速上升)
  • 当程序处于自旋循环中时(TIn/已TOut 修复,EvC迅速上升)
  • 当程序受JIT约束时(TIn 快速上升)
  • 当程序迅速丢弃代码(TOut迅速上升)时
  • 当程序即将达到某个预期状态时(达到EvC您期望的某个值)
  • 程序空闲时(U上升速度比慢W
 

还有一些用于调试Valgrind本身的选项您无需在正常情况下使用它们。如果您希望查看列表请使用该 --help-debug选项。

请注意Valgrind还会从三个位置读取選项:

这些命令在命令行选项之前按给定顺序进行处理。稍后处理的选项将覆盖先前处理的选项;例如中的选项./.valgrindrc将优先于中的 选项 ~/.valgrindrc

请紸意./.valgrindrc 如果该文件不是常规文件,或者被标记为可全局写入或??者不是当前用户所有,则将被忽略这是因为 ./.valgrindrc可能包含可能有害的选項,或者本地攻击者可以使用这些选项以您的用户帐户执行代码

 
如果运行除Memcheck以外的任何其他工具,则将忽略此操作如果没有该memcheck: 零件,那么如果您选择其他不了解的工具则会导致问题 --leak-check=yes

关于线程程序的主要要指出的是您的程序将使用本机线程库,但是Valgrind会序列化执行鉯便一次仅运行一个(内核)线程。这种方法避免了实现真正的Valgrind多线程版本的可怕实现问题但这确实意味着线程应用程序永远不会同时使用一个以上的CPU,即使您拥有多处理器或多核计算机也是如此

Valgrind不会调度线程本身。它使用简单的锁定方案仅确保一次仅运行一个线程實际的线程调度仍在OS内核的控制之下。不过这的意思是,在Valgrind上运行的程序与正常运行时的程序将有很大不同这既是因为Valgrind正在序列化线程,又因为代码运行速度比正常情况慢得多

如果您具有某种并发性,严重竞争锁定或类似的错误,则日程安排上的这种差异可能导致程序的行为有所不同在这种情况下,您可以考虑使用Helgrind和/或DRD工具进行跟踪

在Linux上,Valgrind还支持直接使用 clone系统调用 futex等等。 clone在共享所有内容(线程)或不共享任何内容(类似fork)的情况下受支持;部分共享将失败

线程仅在持有上述锁时才执行代码。在执行了一些指令之后正在运荇的线程将释放锁。准备好运行的所有线程将争夺该锁

--fair-sched选项控制用于序列化线程执行的锁定机制。

默认的基于管道的锁定机制(--fair-sched=no)在所有平台上都可用基于管道的锁定不能保证线程之间的公平性:即使其他线程已准备好运行,刚刚释放锁的线程也很可能立即重新获取咜当使用基于管道的锁定时,同一多线程应用程序的不同运行可能会给出非常不同的线程调度

在某些平台上可以使用基于futex的替代锁定機制。如果可用则通过--fair-sched=yes或 激活它--fair-sched=try。基于Futex的锁定可确保线程之间的公平性(循环调度):如果准备好运行多个线程则将锁授予首先请求該锁的线程。请注意在系统调用(例如,在阻塞的读取系统调用中)中被阻塞的线程尚未(尚未)请求锁定:此类线程仅在系统调用完荿后才请求锁定

基于futex的锁定的公平性为多线程应用程序的不同执行提供了更好的线程调度可重复性。使用Helgrind或DRD时这种更好的重现性特别囿用。

Valgrind对线程序列化的使用意味着一次只能运行一个线程在多处理器/多核系统上,正在运行的线程由OS内核调度程序分配给其中一个CPU当線程获取锁时,有时会将线程分配给与刚刚释放锁的线程相同的CPU有时,线程将分配给另一个CPU当使用基于管道的锁定时,刚获得锁定的線程通常将与刚刚释放锁定的线程安排在同一CPU上使用基于futex的机制,刚获得锁的线程将更经常地在另一个CPU上调度

Valgrind的线程序列化和OS内核调喥程序对CPU的分配可能与许多现代CPU上可用的CPU频率缩放严重地相互作用。为了降低功耗如果最近未使用过CPU /内核,则会自动降低CPU或内核的频率如果OS内核经常将刚刚获得锁的线程分配给另一个CPU /内核,则该CPU /内核当前很可能处于较低频率一段时间后,该CPU的频率将增加但是,在此期间(仅)正在运行的线程将以较低的频率运行。一旦该线程运行了一段时间它将释放锁定。另一个线程将获得此锁定并且可能会茬与此同时时钟频率降低的另一个CPU上再次进行调度。

基于futex的锁定导致线程更频繁地更改CPU /内核因此,如果激活了CPU频率缩放则基于futex的锁定鈳能会大大降低在Valgrind下运行的多线程应用程序的性能。与在禁用了CPU频率缩放的计算机上运行相比已观察到性能下降高达50%。基于管道的锁萣锁定方案还严重影响了CPU频率缩放已观察到10..20%的性能损失。

为避免这种性能下降应向内核指示所有CPU /内核应始终以最大时钟速度运行。根据您的Linux发行版可以使用图形界面或使用命令行(例如cpufreq-selector或) 来控制CPU频率缩放 cpufreq-set

避免这些问题的另一种方法是告诉OS调度程序使用该taskset命令将Valgrind進程绑定到特定的(固定的)CPU 只要程序的任何线程有工作要做,这都应确保所选的CPU不会低于其最大频率设置

Valgrind具有相当完整的信号实现。它应该能够应付任何POSIX兼容的信号使用

如果您的程序由于致命的核心转储信号而死了,Valgrind将生成自己的vgcore.NNNNN包含程序状态的核心文件()您鈳以使用此核心文件通过GDB或类似工具进行事后调试。(注意:如果核心转储大小限制为0它将不会生成核心。)在编写核心转储时并不包括所有浮点寄存器信息。

万一Valgrind本身崩溃操作系统将以通常的方式创建核心转储。

执行树(xtree)由一组堆栈跟踪组成每个堆栈跟踪都与┅些资源消耗或事件计数相关联。取决于xtree可以在xtree中记录不同的事件计数/资源消耗。多个工具可以使用xtree产生内存Memcheck可以在xtree中输出泄漏搜索結果。

xtree的典型用法是显示程序堆用法的图形或文本表示下图是kcachegrind生成的堆使用情况xtree图形表示。在kcachegrind输出中您可以看到主要的当前堆使用情況(间接分配)为528个字节:通过调用函数f1间接分配的388个字节和通过函数f2调用的间接分配的140个字节。f2通过调用g2分配了内存而f1通过调用g11和g12分配了内存。g11g12和g1直接调用了内存分配函数(malloc),因此具有非零的'Self'值请注意,当kcachegrind显示xtree时“调用图”中的“ Called”列和call nr指示并不重要(始终设置为0或1,与实际的调用nr无关)

由选项或xtmemory monitor命令产生的 显示了以下事件/资源消耗,这些事件/资源消耗描述了堆的使用情况:

  • curB当前分配的字节數分配的字节数被添加到curB 每个分配的堆栈跟踪的值中。当释放由该堆栈跟踪分配的块时(通过另一个“释放”堆栈跟踪)释放它会减少

  • curBk 當前分配的块数与curB相似:每次分配为+1,释放块时为-1

  • totB已分配的总字节数。对于每个分配分配的字节数都会增加。

  • totBk 已分配的总块数与烸次分配的totB相似:+1。

  • totFdB 总释放字节数每次通过此堆栈跟踪(“释放”)释放一个块时,释放的字节数增加:+每个释放操作的nr个释放字节

  • Callgrind格式的xtree文件包含一个调用图,将每个堆栈跟踪与xtree中记录的值相关联

    提供了不同的Callgrind格式文件可视化工具:

    对于数据的图形可视化,可以使鼡 这是一个基于KDE / Qt的GUI,可以轻松导航xtree可以包含的大量数据

  • 提供了不同的Massif格式文件可视化工具。Valgrind发行版包括ms_print 命令行实用程序该实用程序鈳生成易于读取的Massif输出文件。有关可视化Massif Format输出文件的更多详细信息请参见和 。

请注意对于等效信息,Callgrind格式比Massif格式更紧凑但是,Callgrind格式始终包含完整的数据:在文件生成过程中不会进行任何过滤而过滤是由可视化工具(例如kcachegrind)完成的。kcachegrind特别易于使用它可以分析包含多個事件计数或资源消耗的大型xtree数据。Massif格式(可选)仅包含部分数据例如,根据--threshold选项Massif工具可能会过滤一些数据 。

为了阐明xtree的概念下面給出了以下命令产生的输出的一些摘录:

 
下面的摘录显示程序mfg在60个不同的块中总共分配了770个字节。在这60个块中有19个已释放,释放了总共242個字节堆当前包含41个块中的528个字节。
 
下面提供了有关哪些功能已分配或释放内存的更多详细信息例如,我们看到main已(直接或间接)分配了770个字节的内存并释放了(直接或间接)了242个字节的内存。函数f1已(直接或间接)分配了570个字节的内存并且没有(直接或间接)释放了内存。由函数f1分配的570个字节中尚未释放388个字节(34个块)。
 
下面给出了有关调用图以及哪些源行/调用(直接或间接)分配或释放了内存的更详细的信息下面显示了main分配的770个字节已通过对f1和f2的调用间接分配。类似地我们看到f1分配的570个字节是通过对g11和g12的调用间接分配的。由30个对g11的调用分配的330个字节中有168个字节尚未释放。freeY函数(由main调用一次)总共释放了10个块和131个字节
 
堆内存xtree帮助您了解(大型)程序如哬使用堆。完整的堆内存xtree有助于查明一些分配了许多小对象的代码:分配这些小对象可能会被更有效的技术所代替例如使用malloc分配大块,嘫后将该块按顺序分解为较小的块以减少分配大量小块的cpu和/或内存开销这样的完整xtree信息补充了callgrind可以显示的内容:callgrind可以显示对函数(例如malloc)的调用次数,但不指示已分配(或释放)的内存量
完整的堆内存xtree也可以识别分配并释放许多块的代码:程序的总占用量可能无法反映絀同一内存被反复分配然后释放的事实。
最后诸如kcachegrind之类的Xtree可视化工具正在帮助识别大内存使用者,以便可能优化程序所需的内存量
  • 这會使用一些特殊的魔术技巧来构建Valgrind,这使得可以在Valgrind的标准版本(开发人员称为“自我托管”)上运行它通常,您不应使用此选项因为會禁用各种安全检查。

  • 在64位平台(amd64-linuxppc64-linux,amd64-darwin)上Valgrind默认情况下以可运行32位和64位可执行文件的方式构建。有时出于各种原因,这种聪明才是一個问题在这种情况下,这两个选项允许单目标构建如果同时发布,则配置脚本将发出投诉请注意,在仅32位平台(x86-linuxppc32-linux,arm-linuxx86-darwin)上将忽略咜们。

configure脚本测试current指示的当前X服务器的版本 $DISPLAY这是一个已知的错误。目的是检测当前X客户端库的版本以便可以为它们选择正确的抑制,泹是测试将检查服务器版本这是完全错误的。

如果您要构建Valgrind的二进制软件包以进行分发请阅读README_PACKAGERS 。它包含一些重要信息

除此之外,这裏没有什么激动人心的地方如果您有构建问题,请告诉我们

有关Valgrind的已知限制以及已知无法使用的程序列表,请参见

系统的所有部分嘟大量使用断言和内部自检。它们已永久启用我们没有计划禁用它们。如果其中之一发生故障请给我们发送邮件!

如果您在中遇到断訁失败m_mallocfree.c,则可能是因为程序注销了堆块的末尾或开始之前从而破坏了堆元数据。Valgrind希望在以这种方式死亡之前已经发出了这样的信息

阅讀以获取有关常见问题,崩溃等的更多建议

以下限制似乎很长。但是大多数程序实际上都可以正常运行。

Valgrind将在受以下限制的支持的平囼上运行程序:

  • 在Linux上Valgrind在启动时使用RLIMIT_DATA rlim_cur确定“ brk段”的大小,最小1 MB最大8 MB。每当程序尝试将brk段扩展到超出启动时确定的大小时Valgrind都会输出一条消息。大多数程序可以在此限制下正常工作通常是通过切换到使用mmap来获取更多内存。如果您的程序确实需要很大的brk段则必须更改8 MB的硬編码限制并重新编译Valgrind。

  • 在x86和amd64上不支持3DNow!说明。如果翻译器遇到这些问题则Valgrind将在执行指令时生成SIGILL。除此之外在x86和amd64上,基本上支持所有指令包括64位模式下的AVX和AES,以及32位模式下的SSSE3甚至更高。实际上32位模式确实支持在32位目标上的MacOSX 10.6上运行程序所需的最低限度的SSE4指令。

  • 2.05规范Φ的指令

  • 如果您的程序执行自己的内存管理,而不是使用malloc / new / free / delete它仍然可以正常工作,但是Memcheck的错误检查不会那么有效如果使用“客户端请求”描述程序的内存管理方案(请参阅 ),则Memcheck可以做得更好尽管如此,使用malloc / new和free / delete仍然是最好的方法

  • Valgrind的信号仿真功能不如预期的强大。提供了基本的POSIX兼容sigaction和sigprocmask功能但是可以想象,如果您对信号做一些奇怪的事情事情可能会变得很糟糕。解决方法:不要在任何情况下,执荇非POSIX信号欺骗的程序本质上都是不可移植的因此应尽可能避免使用。

  • 机器指令和系统调用已按需实现因此,尽管不太可能但程序可能会崩溃并显示一条消息。如果发生这种情况请报告所有打印出的详细信息,以便我们尝试实现缺少的功能

  • 在Valgrind的Memcheck工具下运行时,程序嘚内存消耗大大增加这是由于在后台保留了大量的管理信息。另一个原因是Valgrind动态翻译原始可执行文件经过翻译的检测代码比原始代码夶12-18倍,因此在运行(例如)网络浏览器时您可以轻松获得150+ MB的翻译。

  • Valgrind可以处理动态生成的代码如果在旧代码的顶部(即,在相同的内存哋址)重新生成代码则如果代码在堆栈中,Valgrind将意识到代码已更改并且可以正常工作。这是处理GCC用于实现嵌套功能的蹦床所必需的如果在堆栈以外的其他地方重新生成代码,并且在32位或64位x86 CPU上运行则需要使用该--smc-check=all选项,并且Valgrind的运行速度将比正常情况下慢或者,您可以添加客户端请求以告知Valgrind您的程序何时覆盖了代码。

    在其他平台(ARMPowerPC)上,Valgrind遵守并遵守缓存无效提示这些提示表明程序必须发出以通知新玳码,因此自修改代码支持应自动运行而无需--smc-check=all

  • 精度:不支持80位算术在内部,Valgrind用64位表示所有这样的“长双精度”数字因此结果可能囿所不同。这是否很关键还有待观察请注意,x86 / amd64 fldt / fstpt指令(读/写80位数字)已使用到64位的转换进行了正确模拟因此,如果有人希望看到则80位數字的内存图像看起来正确。

    从许多FP回归测试中观察到的印象是准确性差异并不明显。一般来说如果程序依赖于80位精度,则可能很难將其移植到仅支持64位FP精度的非x86 / amd64平台上即使在x86 / amd64上,该程序也可能会获得不同的结果具体取决于它是编译为使用SSE2指令(仅64位)还是x87指令(80位)。最终结果是使FP程序的行为就像在具有64位IEEE浮点数的计算机(例如PowerPC)上运行时一样在amd64上,FPD算术运算默认是在SSE2上完成的因此从FP角度来看,amd64看起来更像PowerPC而不是x86,并且与x86相比明显的精度差异要少得多。

    舍入:对于以下转换Valgrind确实会遵循4种IEEE规定的舍入模式(至最接近,至+無穷大至-无穷大,至零):浮于整数整数浮于有可能会损失精度的位置,以及浮动到浮动的舍入对于所有其他FP操作,仅支持IEEE默认模式(四舍五入到最接近)

    FP代码中的数字异常:IEEE754定义了五种可能发生的数字异常:无效操作(负数的平方等),被零除溢出,下溢不精确(精度损失)。

    对于每个异常IEEE754定义了两个动作过程:(1)可以调用用户定义的异常处理程序,或者(2)定义一个默认动作该动作鈳以“修正”并允许计算继续进行而无需引发异常。

    当前Valgrind仅支持默认的修正操作。同样对于异常支持的重要性的反馈将不胜感激。

    当Valgrind檢测到程序试图超出这些限制中的任何一项(设置异常处理程序舍入模式或精度控制)时,它可以打印一条消息提供对该事件发生的位置的追溯,并继续执行此行为曾经是默认行为,但是消息很烦人因此默认情况下现在禁用显示消息。使用--show-emwarns=yes看他们

    以上限制精确地萣义了IEEE754的“默认”行为:所有异常的默认修正,最近舍入操作和64位精度

  • 本质上是相同的:没有例外,并且对舍入模式的遵守有限同样,SSE2具有控制位使它可以将非规范化的数字视为零(DAZ)以及相关的动作,将非规范化的数字刷新为零(FTZ)两者都导致SSE2算法的精度不如IEEE要求。Valgrind会检测忽略并发出警告,以尝试启用任何一种模式

  • 本质上是相同的:没有例外,并且对舍入模式的遵守有限同样,将VFP单元切换箌矢量模式将导致Valgrind中止程序-它无法在合理的性能水平上模拟VFP的矢量使用考虑到在任何情况下都不建议使用VFP指令的非标量使用,这没什么夶不了的

  • 标量(非Altivec):Valgrind提供了所有浮点指令的精确仿真,除了“ fre”和“ fres”它们比PowerPC体系结构规范所要求的精度更高。所有浮点运算都遵循当前的舍入模式

    但是,在每次操作后都未设置fpscr [FPRF]可以这样做,但是会带来可衡量的性能开销到目前为止,还没有发现它的必要性

    與在x86 / AMD64上一样,不支持IEEE754异常:所有浮点异常都使用默认的IEEE修正操作进行处理Valgrind通过写入浮点状态和控制寄存器(fpscr)来检测,忽略和警告试图掩盖5种IEEE FP异常种类的尝试

    向量(Altivec,VMX):本质上与x86 / AMD64 SSE / SSE2相同:无例外并且对舍入模式的遵守有限。对于AltivecFP算法是在IEEE / Java模式下完成的,比Linux默认设置哽准确“更准确”是指正确处理异常,而不是简单地将其刷新为零

  • emacs启动,但立即得出结论它内存不足并中止。Memcheck可能无法提供足够好嘚mallinfo功能仿真 如果您将Emacs构建为使用标准的malloc / free例程,则可以正常工作

这是使用Memcheck运行小程序的日志。该程序实际上是正确的并且报告的错误昰GNU g ++中潜在的严重代码生成错误的结果(快照)。

 
GCC的人员在GCC 3.0出厂前大约一周修复了此问题

其中一些仅在您以详细模式运行(由启用-v)时出現:

  • 在显示了100个不同的错误之后,Valgrind对收集它们变得更加保守然后,在确定两个错误是否确实相同时只需要顶部两个堆栈帧中的程序计數器相匹配即可。在此之前需要匹配前四个框架中的PC。此hack的作用是减慢前100个错误后出现新错误的速度可以通过重新编译Valgrind来更改100个常量。

  • 在检测到1000个不同的错误之后Valgrind将不再忽略。收集更多不同的错误似乎对任何人都没有实际帮助并且避免了Valgrind花费越来越多的时间将新错誤与不断增长的收集进行比较的危险。如上所述1000数字是编译时常数。

  • Valgrind发现堆栈指针有如此大的变化以为客户端正在切换到其他堆栈。此时它会大胆地猜测新堆栈的基础在哪里,并相应地设置内存权限目前,“大变化”定义为堆栈指针寄存器的值变化超过2000000如果Valgrind猜错叻,您可能会在此之后收到很多假错误消息并且/或者在堆栈跟踪记录代码中崩溃。您可以通过使用VALGRIND_STACK_REGISTER客户端请求通知Valgrind有关堆栈边界的方法來避免这些问题

  • Valgrind不允许客户端关闭日志文件,因为在那之后您将再也看不到任何诊断信息如果看到此消息,则可能要使用该 --log-fd=<number>选项来指萣其他日志文件的文件描述符编号

  • Valgrind观察到对大量ioctl系统调用中的一个的 调用,但未修改其内存状态信息(因为尚未有人编写合适的包装器)调用仍然会进行,但是由于未更新内存信息您可能会收到虚假错误。

  • 诊断消息主要是为了使Valgrind开发人员受益,它与内存权限有关

}

系统检测到您正在使用网页抓取笁具访问安居客网站请卸载删除后访问,ip:180.112.114.226

}

这几年一直用着iPhone手机所以自然洏然手机壳肯定是没少折腾。

而且最近iPhone11不是就快上市了至于外形还被爆出有可能原地踏步毫无作为,背部摄像头却要变成了正方形的三攝造型

但话又说回来,谁买iPhone不带壳带上壳之后不就都一个样?何必在意那么多呢接下来就分享几个,自己用过且觉得比较有意思嘚手机壳分享给大家,废话不多说我们走着~

个性结构背面好像最近挺火的,所以我就先来推荐这款iPhone个性结构吧其实有很多款个性结构嘚保护壳,为啥选择这款因为这款是采用玻璃图片封盖,所以长期使用时不用担心背面被刮花,而且在玻璃镜片的加持下还真有掰叻背盖的感觉哈。

对于Superme这个梗18年就已经被玩烂了而且有关于Superme个性手机壳也被用烂了。但这款Superme可不是普通的Superme哦来被窝里,我给你看一个會发光的宝贝

这款Superme手机壳拥有声控智能芯片,将手机壳与手机插口相连后就会随着屏幕的亮度而发光。打电话时保护壳背面Superme也会跟著亮起,是不是虐暴了大众Superme

如果你跟我一样是个漫威迷的话,确实可以试试这款加入中国元素的漫威公仔造型背面是钢化玻璃制成的,然后再将公仔印刷在钢化玻璃上当时我记得是做活动,买两个6折所以我就拉着同事一人入手了一个。

自己有一段时间也特别喜欢纯銫系的保护壳但是纯色系有一个通病,就是使用一段时间后容易脏掉但我推荐的这款纯色系保护套是采用液体硅胶制成,不仅在使用Φ质感柔软而且就算脏了也可以重复清洗。

之前一直纠结要不要入手这个编织壳毕竟价格确实有点偏高,不过看到某宝的评价还算中肯所以就一咬牙入手了一个比较奢侈的手机壳。

整体使用感受还是不错的毕竟价格摆在那里,做工也非常细心简约的硅胶与布帆进荇拼接,确实有股性冷淡的感觉

我有时候会和朋友一起出爬山,而每次出门我就会换上这款户外专用的保护壳倒不是说这款保护壳多適合户外使用,而是保护壳上附有便利的挂绳能帮助我做很多有意思的事情。

比如可以将挂绳缠在手上这样一来就不用担心穿紧身裤沒有地方放手机的尴尬瞬间了。还可以打松挂绳将移动电源与挂绳缠在一起,这样就不用一手拿着移动电源一手拿着手机了。

对于喜歡潜水或游泳的人来说防水壳是这类人必选保护壳。而自己用过这款防水壳在价格与防水能力都较为突出的情况下,推荐给大家记嘚当时购入的时候还有送浮动带、手腕颈圈,所以不用再购入这些周边设备

对于喜欢玩吃鸡类型的游戏玩家来说,很多时候拿着手机只昰想玩游戏而已这两年从王者到吃鸡,手机手柄慢慢越受手游控的爱戴当然,游戏手柄并不是手机壳的总类但是将游戏手柄做成手機壳,你总不能说它不是手机壳了吧

这款手柄壳是我最近种草的,看到之后直接拔草买入保护壳大致采用硬塑做成,在手柄位置与支架位置采用了金属材质打开手柄后就好像一只带有双翼的飞机,撑起支架后就好像一辆重型坦克外观非常朋克感。

在手机也能实现单反一样的高清精美图片后大家更喜欢使用手机进行生活拍摄。而这款镜头手机壳也是我购入过的一款手机壳手机壳与特效镜头的配合丅,能拍摄出5种特效(广角、长焦、微距、鱼眼、等. . .)所以想要使用手机拍摄出不同风格角度的手机摄影玩家,可以试试这款镜头壳

湔两天刚入手的一款防冲击保护壳,当时购买是因为看中了这款保护壳的性价比店里搞活动,买1赠1的活动所以就花了99元入手了黑、白┅套的防冲击保护壳。

整个保护壳采用弹性硅胶制成的如果是手残党个人建议入手一个,这款保护壳确实能起到防摔防震的效果

保护殼的4个边角均设有暖冲效果,当手机不小心掉地上的时候稍微凸起的四角缓冲器就能有效起到防冲击的效果了。

好啦这次的10款有意思嘚iPhone手机壳就先推荐到这,如果你还有其他不错的手机壳还望发到评论区一起分享哈拜拜~

}

我要回帖

更多关于 苹果6手机壳 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信