Valgrind getting strange error

779 views Asked by At

Hi why I am getting this strange Valgrind error

==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)

I want try to get Memory use. This is my code:

#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;
}

Without Valgrind my program is working fine:

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

There are 1 answers

2
Baum mit Augen On BEST ANSWER

First of all and most importantly: This is not good C++ code, not even decent. For example, some of your #includes are wrong, like <stdio.h> should be <cstdio> instead. The worst thing here are those #defines that make your code utterly unreadable. You really should read a good book on C++!


For better readability I produced the pre-processor output of your code (minus the includes of course). It looks like this:

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;
}

The line causing the error is

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

This is invalid because you pass a pointer to the internal buffer of the local std::string object in name() to fopen. This object ceases to exist at the end of name(), and thus the pointer does not point to valid memory anymore.

Note that you also have a memory leak in your add methods: You new up std::string objects that never get deleted.