See the program below:
#include <cstdio>
#include <cstring>
#include <iostream>
class Chaine {
private:
char* _donnees;
unsigned int _taille;
public:
Chaine();
Chaine(const char*);
~Chaine();
unsigned int taille() const;
};
Chaine::Chaine():_taille(0) {
_donnees=new char[1];
_donnees[0]='\0';
}
Chaine::Chaine(const char *s) {
_taille = std::strlen(s);
_donnees = new char[_taille + 1];
std::strcpy(_donnees, s);
std::printf("%s(%d): %s\n", __FILE__, __LINE__, __func__);
}
Chaine::~Chaine() {
if(*_donnees == 0){
std::printf("_donnees points to freed block\n");
}
else{
std::printf("_donnees points to freed block\n");
delete[] _donnees;
_donnees=NULL;
}
std::printf("%s(%d): %s\n", __FILE__, __LINE__, __func__);
}
unsigned int Chaine::taille() const{
return _taille;
}
int main() {
Chaine s1("une chaine");
Chaine *s2 = new Chaine("s3");
Chaine s3 = s1;
delete s2;
}
I compiled using g++ -Wall -o test test.cpp
then run valgrind --leak-check=full ./test
and got messages below:
/test
==5638== Memcheck, a memory error detector
==5638== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==5638== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==5638== Command: ./test
==5638==
test.cpp(29): Chaine
test.cpp(29): Chaine
_donnees points to freed block
test.cpp(41): ~Chaine
_donnees points to freed block
test.cpp(41): ~Chaine
==5638== Invalid read of size 1
==5638== at 0x804886D: Chaine::~Chaine() (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== by 0x804895F: main (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== Address 0x4353028 is 0 bytes inside a block of size 11 free'd
==5638== at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5638== by 0x80488A3: Chaine::~Chaine() (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== by 0x8048953: main (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638==
_donnees points to freed block
==5638== Invalid free() / delete / delete[] / realloc()
==5638== at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5638== by 0x80488A3: Chaine::~Chaine() (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== by 0x804895F: main (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== Address 0x4353028 is 0 bytes inside a block of size 11 free'd
==5638== at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5638== by 0x80488A3: Chaine::~Chaine() (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638== by 0x8048953: main (in /home/qliang/Documents/ENSEIRB/cpp/td2/chaine2/test)
==5638==
test.cpp(41): ~Chaine
==5638==
==5638== HEAP SUMMARY:
==5638== in use at exit: 0 bytes in 0 blocks
==5638== total heap usage: 3 allocs, 4 frees, 22 bytes allocated
==5638==
==5638== All heap blocks were freed -- no leaks are possible
==5638==
==5638== For counts of detected and suppressed errors, rerun with: -v
==5638== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
I the deconstructor, I want to check if the memory _donnees points to has been freed to avoid re-free. One solution(maybe bad solution) is to declare a static integer in deconstructor, like
Chaine::~Chaine() {
static int num_free = 0;
if(num_free == 1){
std::printf("_donnees points to freed block\n");
}
else{
std::printf("_donnees points to freed block\n");
delete[] _donnees;
num_free = 1;
_donnees=NULL;
}
std::printf("%s(%d): %s\n", __FILE__, __LINE__, __func__);
}
But I want to know if there is some way like *_donnees == NULL to check if the block of memory is freed or not.
And, why valgrind displays messages:
==5638== Invalid read of size 1
==5638== Invalid free() / delete / delete[] / realloc()
and why each of these messages just show once?