【问题标题】:Valgrind reports errors for a very simple C programValgrind 报告一个非常简单的 C 程序的错误
【发布时间】:2015-01-08 14:55:24
【问题描述】:

我正在向Learn C The Hard Way 学习 C 语言。我在 exercise 6 上,虽然我可以让它工作,但 valgrind 报告了很多错误。

这是从文件 ex6.c 中剥离出来的最小程序:

#include <stdio.h>

int main(int argc, char *argv[])
{
    char initial = 'A';
    float power = 2.345f;

    printf("Character is %c.\n", initial);
    printf("You have %f levels of power.\n", power);

    return 0;
}

Makefile 的内容就是CFLAGS=-Wall -g

我使用$ make ex6 编译程序(没有编译器警告或错误)。使用$ ./ex6 执行会产生预期的输出。

当我使用$ valgrind ./ex6 运行程序时,我遇到了无法解决的错误。这是完整的输出:

==69691== Memcheck, a memory error detector
==69691== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==69691== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info
==69691== Command: ./ex6
==69691==
--69691-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option
--69691-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 2 times)
--69691-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 4 times)
==69691== Conditional jump or move depends on uninitialised value(s)
==69691==    at 0x1003FBC3F: _platform_memchr$VARIANT$Haswell (in /usr/lib/system/libsystem_platform.dylib)
==69691==    by 0x1001EFBB6: __sfvwrite (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x1001FA005: __vfprintf (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x10021F9CE: __v2printf (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x10021FCA0: __xvprintf (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x1001F5B91: vfprintf_l (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x1001F39F7: printf (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x100000F1B: main (ex6.c:8)
==69691==
Character is A.
==69691== Invalid read of size 32
==69691==    at 0x1003FBC1D: _platform_memchr$VARIANT$Haswell (in /usr/lib/system/libsystem_platform.dylib)
==69691==    by 0x1001EFBB6: __sfvwrite (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x1001FA005: __vfprintf (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x10021F9CE: __v2printf (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x10021FCA0: __xvprintf (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x1001F5B91: vfprintf_l (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x1001F39F7: printf (in /usr/lib/system/libsystem_c.dylib)
==69691==    by 0x100000F31: main (ex6.c:9)
==69691==  Address 0x100809680 is 32 bytes before a block of size 32 in arena "client"
==69691==
You have 2.345000 levels of power.
==69691==
==69691== HEAP SUMMARY:
==69691==     in use at exit: 39,365 bytes in 429 blocks
==69691==   total heap usage: 510 allocs, 81 frees, 45,509 bytes allocated
==69691==
==69691== LEAK SUMMARY:
==69691==    definitely lost: 16 bytes in 1 blocks
==69691==    indirectly lost: 0 bytes in 0 blocks
==69691==      possibly lost: 13,090 bytes in 117 blocks
==69691==    still reachable: 26,259 bytes in 311 blocks
==69691==         suppressed: 0 bytes in 0 blocks
==69691== Rerun with --leak-check=full to see details of leaked memory
==69691==
==69691== For counts of detected and suppressed errors, rerun with: -v
==69691== Use --track-origins=yes to see where uninitialised values come from
==69691== ERROR SUMMARY: 5 errors from 2 contexts (suppressed: 0 from 0)

我在 OS X 优胜美地。 Valgrind 通过brew 使用此命令$ brew install valgrind --HEAD 安装。

那么,有谁知道这里的问题是什么?如何修复 valgrind 错误?

【问题讨论】:

  • 您是否链接到某个外部库?
  • 在我的 Linux 上,您的示例没有报告任何错误。在“相关链接”侧边栏中,有 one that suggests using suppression files
  • @IngoLeonhardt:float 类型的可变参数被提升为double,所以这应该不是问题。 (并且正确的原型在&lt;stdio.h&gt;,包含在内。)
  • 这是--partial-loads-ok=yes 应该修复的误报的特征。
  • 具有相同问题但答案数组略有不同的类似主题:Valgrind on OS X Yosemite, giving bogus errors?

标签: c valgrind


【解决方案1】:

如果您通过 Valgrind 运行的程序正是您在问题中发布的程序,那么它显然没有任何内存泄漏。事实上,你自己甚至都不使用 malloc/free!

在我看来,这些是 Valgrind 在 OS X 上检测到的虚假错误/误报(仅限!),类似于 what happened to myself some time ago

如果您可以访问其他操作系统,例如一台 Linux 机器,尝试在该系统上使用 Valgrind 分析程序。

编辑:我自己没有尝试过,因为我现在无法使用 Mac,但你应该尝试一下 M Oehm 建议:try to use a supressions file as mentioned in this other SO question.

【讨论】:

  • 我找不到 OS X Yosemite 的抑制文件。 SA 答案中的那个对 Valgrind 输出没有任何影响。另一方面,在 vagrant 中使用 linux 执行相同的步骤会产生干净的 Valgrind 输出。
  • 我在自己的机器上确认了这一点。我在 Mac OS X 上复制了这个简单的程序,用 Valgrind 运行,得到了条件跳转。
【解决方案2】:

此问题已针对 Darwin 14.3.0 (Mac OS X 10.10.2) 修复,使用 Xcode6.2 的 Valgrind r14960 with VEX r3124 和 Xcode 6.3 的 Valgrind r15088

如果您使用的是 Macports(在撰写本文时),sudo port install valgrind-devel 会给您Valgrind r14960 with VEX r3093

这是我要安装的构建脚本Valgrind r14960 with VEX r3124

#! /usr/bin/env bash

mkdir -p buildvalgrind
cd buildvalgrind
svn co svn://svn.valgrind.org/valgrind/trunk/@14960 valgrind
cd valgrind
./autogen.sh
./configure --prefix=/usr/local
make && sudo make install

# check that we have our valgrind installed
/usr/local/bin/valgrind --version 

(参考:http://calvinx.com/2015/04/10/valgrind-on-mac-os-x-10-10-yosemite/

我的 macports 安装的 valgrind 位于 /opt/local/bin/valgrind

如果我现在运行

/opt/local/bin/valgrind --leak-check=yes --suppressions=`pwd`/objc.supp ./ex6

我将得到与您上面描述的完全相同的错误。 (在这里使用我的objc.supp 文件https://gist.github.com/calvinchengx/0b1d45f67be9fdca205b

但如果我跑了

/usr/local/bin/valgrind --leak-check=yes --suppressions=`pwd`/objc.supp ./ex6

一切都按预期工作,我没有出现系统级内存泄漏错误。

【讨论】:

    【解决方案3】:

    this 主题来看,我认为 valgrind 不能保证在您的平台上给出正确的结果。如果可以,请在其他平台上尝试此代码。

    罪魁祸首要么在于 valgrid 本身,要么在于您系统的 printf 实现,这两者对您来说都是不切实际的。

    Rerun with --leak-check=full to see details of leaked memory. 这应该会给你一些关于你正在经历的泄漏的更多信息。如果没有任何帮助,您可以创建一个suppression file 以阻止显示错误。

    【讨论】:

    • 不幸的是,您目前无法为“32 号的无效读取”创建抑制文件。 Darwin 端口中有这个新错误,但不支持抑制大小大于 16 的错误。实现这个应该是时间问题(听起来像是一个微不足道的修复)。
    猜你喜欢
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多