1

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?

qingl97
  • 327
  • 4
  • 14
  • Can't you just use an `std::string` and be done with it? – juanchopanza Jan 09 '14 at 21:13
  • Your class has dynamic-managed members, yet is not practicing the [Rule of Three](http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)). Use `std::string` and don't reinvent the wheel. – WhozCraig Jan 09 '14 at 21:14
  • possible duplicate of [What is The Rule of Three?](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – juanchopanza Jan 09 '14 at 21:16

1 Answers1

0

You are violating the Rule of Three. You should define a copy constructor and a copy assignment operator.

NPE
  • 486,780
  • 108
  • 951
  • 1,012