0

Out of fun, I decided to see what gdb would say about this code, which is meant to attempt to use methods of an already destroyed object.

#include <iostream>

class ToDestroy
{
public:
  ToDestroy() { }
  ~ToDestroy() {
    std::cout << "Destroyed!" << std::endl;
  }
  void print() {
    std::cout << "Hello!" << std::endl;
  }
};

class Good
{
public:
  Good() { }
  ~Good() { }
  void setD(ToDestroy* p) {
    mD = p;
  }
  void useD() {
    mD->print();
  }
private:
  ToDestroy* mD;
};

int main() {
  Good g;
  {
    ToDestroy d;
    g.setD(&d);
  }
  g.useD();
  return 0;
}

The output is (built with -O0 flag):

Destroyed!

Hello!

Allocating d in the heap and deleting it causes the same behaviour (i.e., no crash).

I assume the memory has not been overwritten and C++ is 'tricked' into using it normally. However, I am surprised about the fact that, when allocating on the heap and deleting, one can use memory not assigned to them.

Can someone provide any more insight about this? Does this mean that when trying to dereference a pointer, if that memory happens to have something 'coherent' for our context the execution would not cause a SEGFAULT despite the memory not having been assigned to us?

Community
  • 1
  • 1
user2891462
  • 3,033
  • 2
  • 32
  • 60
  • 3
    The highly rated reply on http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope is related – jcoder Mar 19 '15 at 11:10

2 Answers2

2

A segfault happens when you try to access an address that the OS forbids you to access. This can be because the mem behind the address is not allocated to you process, or because it does not exist or whatever. So you are now trying to access a piece of memory that is still allocated to your process, so no segfault.

Malloc (the one that manages your heap) works with certain buffers to limit the amount of syscalls. So there is uninitialized mem that you can access.

Cheiron
  • 3,620
  • 4
  • 32
  • 63
  • Why is it still allocated to my process if I have freed it? Does freed memory remain assigned to the last process which used it but marked as "can be reassigned"? – user2891462 Mar 19 '15 at 12:17
  • 1
    Readup on malloc and mmap. The basic priciple: when you malloc this first time malloc mmaps a pool. mmap is a syscall, and thus a very "heavy" call. Then, all succesesive malloc calls will use this pool until it is completely full. So a free will just free up a part of this pool for malloc to reassign. Unless an entire pool is freed up, then the pool might be given back to the OS with munmap, dependend on the malloc implementation. – Cheiron Mar 19 '15 at 12:53
  • @Cheiron: as I said in my answer - there is no memory access at all. – stefan Mar 19 '15 at 23:34
2

You pass an invalid this pointer to print but it is never dereferenced as print is not virtual nor is it accessing any member.

stefan
  • 3,681
  • 15
  • 25
  • I know I'm wrong here, but mD->print() is the same as (*mD).print(), so there is a pointer being dereferenced, right? – user2891462 Mar 19 '15 at 11:39
  • 1
    the compiler knows the type and calculates the address of print. the pointer is passed as first (invisible) argument. – stefan Mar 19 '15 at 11:44