Valgrind的越来越奇怪的错误

问题描述:

嗨为什么我收到这个奇怪的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: [email protected]@GLIBC_2.1 (fileops.c:332) 
==18572== by 0x421349A: __fopen_internal (iofopen.c:90) 
==18572== by 0x421350A: [email protected]@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 
+0

我知道我有一些错误。这就是为什么我要求 – thohmy

+3

@thohmy首先,关于代码错误的问题需要[SSCCE](http://www.sscce.org)以及明确的问题陈述。但是,你的代码的真正问题在于它是如此糟糕的“样式”,甚至很难调用C++。这只是一个难以理解的混乱。我不想在这里侮辱你,我只想说,这将是从使用一个像样的书从头学C++您的最佳利益(见上面的链接)。 –

+2

@BaummitAugen他有SSCCE :)代码可能来自www.ioccc.org,这个问题可能是一个坏的笑话。 –

第一:这是良好的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"); 

这是无效的,因为你在name()一个指针传递给当地std::string对象的内部缓冲区fopen。该对象在name()结束时不再存在,因此指针不再指向有效内存。

注意,也有内存泄漏在add方法:你newstd::string对象永远不会被删除。

+0

哇,真好!谢谢 – thohmy

+1

@thohmy没问题。但* *请接受我的建议,并学习如何写出更好的C++。你现在正在做对你没好处,我保证。 –