obj in memory deleted multiple times: no runtime error !?!

Hi!

This is a question about "reserving memory" (new...) and then freeing it with delete.

Usually if I delete some memory more than once... a runtime error crash occurs.

But I have an example below, where no runtime error occurs. Even though the memory is deleted 3 times!! (I'm using gcc's g++)
The example uses smart-pointers.

My question:
*Am I correct that the code below has errors?
*Am I correct that g++ does not detect these errors? What do other compilers do?
*Could this be a compiler bug? Should I contact the gcc team?

The int-memory-object (pointed-to by ip) is deleted 3 times: see lines 59, 62, 67

The deleted int-memory-object, can still be accessed: see lines 61, 64, 68


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// 
// Below an int-object is created with new int(1)
// Usually a runtime error occurs if an object is deleted 2 or more times.
// But in the course of the execution, the object is deleted 3 times --> Why does no runtime error occur?


#include <iostream>

using std::cout;
using std::endl;

class U_a
{
  friend class B;
  U_a(int *p) : ip(p), use(1) {}
  ~U_a() {
    std::cout << "Delete " << ip << std::endl;
    delete ip;
  }
  int *ip;
  size_t use; // use-counter, used by smart-pointer...
};

class B // uses smart pointers
{
public:
  B(int *p) : ptr(new U_a(p)) {}
  B(const B &rhs) : ptr(rhs.ptr) { // not used
    ++ptr->use;
  }
  B &operator=(const B &rhs) { // not used
    ++rhs.ptr->use;
    if (--ptr->use == 0)
      delete ptr;
    ptr = rhs.ptr;
    return *this;
  }
  int get_ip_val() {
    return *ptr->ip;
  }
  ~B() {
    if (--ptr->use == 0)
      delete ptr;
  }
private:
  U_a *ptr;
};


int main()
{

  int *ip = new int(1); // created "object-pointed-to-by ip" and give it initial value 1
  {
    B b1(ip);
    {
      B b2(ip);         // deliberate bad use of smart-pointer class. This is not the copy constructor! ;)
      cout << "Val: " << b1.get_ip_val() << endl;
    }                   // b2's destructor has run and deleted "object-pointed-to-by ip"!

    cout << "Val: " << b1.get_ip_val() << endl; // 1)*** Why can we still get "object-pointed-to-by ip"? Why is there no runtime error?
  }          // 2)*** b1's destructor has run and deleted "object-pointed-to-by ip" the second time!!! Why is there still no runtime error?

  *ip = 4;   // 3)*** Why is there still no runtime error?

  std::cout << "Delete " << ip << std::endl;
  delete ip; // here we delete "object-pointed-to-by ip" a 3rd time     4)*** Why is there still no runtime error?
  *ip = 5;   // 5)*** Why is there still no runtime error?

  return 0;
}
Last edited on
I've asked about it here...
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49728

I hope it's not something trivial, or something that isn't even an error!
The problem is you assign "use" to 1 in your U_a constructor, but then you also increment it when you make the point in b1/b2. However, it DOES crash at line 64 on my, due to writing on memory you don't own.
Hi firedraco.
No... "use" is not incremented in the code.
It would be incremented in the "copy constructor" and "assignment operator"... but those are not used in the code anyway.

It does not crash on my machine. Linux running gcc v 4.5.2 using g++
Last edited on
I tried to replace the line
int *ip = new int(1);
with
int *ip = new int[3];

If the index of the array is 1,2 or 3 there is no crash. But the moment I change this to 4 or more than 4 crash comes consistently.

Hi ashishkumar,
that's unrelated. PS: the only valid indices (index's) of int *ip = new int[3]; are: ip[0], ip[1] and ip[2]
Ok the issue has been resolved at the gcc bugtracker.
See the comment of Jonathan Wakely
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49728#c2

according to whom it's not the compiler's job to diagnose the double delete.
Topic archived. No new replies allowed.