Valgrind得到了奇怪的错误

时间:2015-06-12 16:19:03

标签: c++ valgrind

你好我为什么会得到这个奇怪的Valgrind错误

==18572== Memcheck, a memory error detector
==18572== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==18572== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==18572== Command: ./test
==18572== 
==18572== Syscall param open(filename) points to unaddressable byte(s)
==18572==    at 0x42891B3: __open_nocancel (syscall-template.S:81)
==18572==    by 0x421E98B: _IO_file_open (fileops.c:227)
==18572==    by 0x421EB3A: _IO_file_fopen@@GLIBC_2.1 (fileops.c:332)
==18572==    by 0x421349A: __fopen_internal (iofopen.c:90)
==18572==    by 0x421350A: fopen@@GLIBC_2.1 (iofopen.c:103)
==18572==    by 0x8049141: main (test.cpp:46)
==18572==  Address 0x435c784 is 12 bytes inside a block of size 30 free'd
==18572==    at 0x402A808: operator delete(void*) (vg_replace_malloc.c:507)
==18572==    by 0x4109EC7: std::string::_Rep::_M_destroy(std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.20)
==18572==    by 0x8049954: _M_dispose (basic_string.h:249)
==18572==    by 0x8049954: ~basic_string (basic_string.h:547)
==18572==    by 0x8049954: name() (test.cpp:39)
==18572==    by 0x8049127: main (test.cpp:46)
==18572== 
Private: 32164
Pss: 32234
Referenced: 33184
Rss: 33184
Shared: 1020
Swap: 0
==18572== 
==18572== HEAP SUMMARY:
==18572==     in use at exit: 88,560 bytes in 7,872 blocks
==18572==   total heap usage: 8,213 allocs, 341 frees, 96,854 bytes allocated
==18572== 
==18572== LEAK SUMMARY:
==18572==    definitely lost: 15,744 bytes in 3,936 blocks
==18572==    indirectly lost: 72,816 bytes in 3,936 blocks
==18572==      possibly lost: 0 bytes in 0 blocks
==18572==    still reachable: 0 bytes in 0 blocks
==18572==         suppressed: 0 bytes in 0 blocks
==18572== Rerun with --leak-check=full to see details of leaked memory
==18572== 
==18572== For counts of detected and suppressed errors, rerun with: -v
==18572== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

我想尝试使用内存。这是我的代码:

#include <stdio.h>
#include <functional>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <sstream>
#include <map>

#define rss_str "Rss"
#define shared_str "Shared"
#define private_str "Private"
#define swap_str "Swap"
#define pss_str "Pss"
#define referenced_str "Referenced"
#define sep ':'
#define readopenfile "r"
#define i int
#define s std::string
#define l(A) (new s(A))->length()
#define conc(...) str(__VA_ARGS__).c_str()
#define eq(A,B) strncmp(A,B,l(A))==0
#define fun(B) strchr(B,sep)+1
#define smap std::map<s,i>
#define foreach(m) for(auto it : m) { auto a = it.first; auto b = it.second;
#define foreachend }
#define strs std::stringstream
#define beginfile(F) FILE *fp = fopen(F(), readopenfile);
#define endfile fclose(fp);

template<class A> s str(A a)                        { strs ss; ss<<a; return ss.str(); }
template<class A, class ... B> s str(A a, B...b)    { strs ss; ss<<a<<str(b...); return ss.str(); }
template<class A, class X>
void add(smap &m, X x, A a) { if(eq(a,x))m[a] += atoi(fun(x));}
template<class A, class X, class ... B>
void add(smap &m, X x, A a, B...b) { if(eq(a,x))m[a] += atoi(fun(x)); add(m, x, b...); }

const char* name() { return conc("/proc/",getpid(),"/smaps"); }

i main(i __attribute__((unused)) argc, char __attribute__((unused)) *args[])
{
    char b[256];
    smap m;

    beginfile(name)
        while(fgets(b, 256, fp))
            add(m,b,rss_str,shared_str,private_str,swap_str,pss_str,referenced_str);

        foreach(m)
            i value = b;
            fprintf(stderr, "%s: %d\n", a.c_str(), b);
        foreachend
    endfile

    return 1;
}

没有Valgrind,我的程序运行正常:

Private: 1004
Pss: 1121
Referenced: 1952
Rss: 1952
Shared: 948
Swap: 0

1 个答案:

答案 0 :(得分:1)

首先,最重要的是:这是良好的C ++代码,甚至不是很好。例如,您的某些#includes错误,例如<stdio.h>应为<cstdio>。最糟糕的是那些使你的代码完全不可读的#define。您 真的 应该在C ++上阅读good book

为了更好的可读性,我生成了代码的预处理器输出(当然减去包含)。它看起来像这样:

template<class A> std::string str(A a) { std::stringstream ss; ss<<a; return ss.str(); }
template<class A, class ... B> std::string str(A a, B...b) { std::stringstream ss; ss<<a<<str(b...); return ss.str(); }
template<class A, class X>
void add(std::map<std::string,int> &m, X x, A a) { if(strncmp(a,x,(new std::string(a))->length())==0)m[a] += atoi(strchr(x,':')+1);}
template<class A, class X, class ... B>
void add(std::map<std::string,int> &m, X x, A a, B...b) { if(strncmp(a,x,(new std::string(a))->length())==0)m[a] += atoi(strchr(x,':')+1); add(m, x, b...); }

const char* name() { return str("/proc/",getpid(),"/smaps").c_str(); }

int main(int __attribute__((unused)) argc, char __attribute__((unused)) *args[])
{
    char b[256];
    std::map<std::string,int> m;

    FILE *fp = fopen(name(), "r");
        while(fgets(b, 256, fp))
            add(m,b,"Rss","Shared","Private","Swap","Pss","Referenced");

        for(auto it : m) { auto a = it.first; auto b = it.second;
            int value = b;
            fprintf(stderr, "%s: %d\n", a.c_str(), b);
        }
    fclose(fp);

    return 1;
}

导致错误的行是

FILE *fp = fopen(name(), "r");

这是无效的,因为您将指针传递到std::stringname()的本地fopen对象的内部缓冲区。该对象在name()的末尾不再存在,因此指针不再指向有效的内存。

请注意,add方法中也存在内存泄漏:您new向上std::string个永远不会被删除的对象。