1

Let's consider follwing code. In fact this is narrowed problem I found using gmock and mocking void(void) method.

class Base {
 public:
  virtual ~Base() {}
};

class Derived : public Base
{
 public:
  void GetValueAndDelete()  { delete this; } //here we crash
};

int main() {
  Derived* p = 0;
  p->GetValueAndDelete();
}

Building it with:

/tools/gcc6.1/bin/g++ --version
g++ (GCC) 6.1.0

with optimization level different than -O0 and running the result causes segmentation fault.

Is it gcc bug or something with c++ code (yes, yes, I know that it uses side effects, but it works with other compilers and without optimization as well)

a3f
  • 8,517
  • 1
  • 41
  • 46
Kamil_H
  • 501
  • 1
  • 5
  • 12
  • 3
    you dereference a null pointer, what do you expect to happen? – 463035818_is_not_an_ai Jul 13 '16 at 12:57
  • 2
    I would believe that dereferencing a null pointer is grounds for segmentation faults in any circumstance; it's undefined behaviour. – N. Shead Jul 13 '16 at 12:57
  • 5
    What? You call a function on a null pointer and wonder why it doesn't work? – Bo Persson Jul 13 '16 at 12:57
  • 2
    Be very careful when doing `delete this`, it basically is the same as demolishing the building you are in. If you're careful the debris won't kill you, but in most cases bad things are going to happen. – Some programmer dude Jul 13 '16 at 12:58
  • 1
    "it works with other compilers" Do you mean it doesn't print a crash message? – n. m. could be an AI Jul 13 '16 at 12:59
  • @BoPersson: Dereferencing null pointer and calling method in this way that does not use any members is fine. What is calling method on pointer? It is simply calling method and passing hidden 'this' argument. Noting is called "on" pointer. Deleting this is nothing special. You should only take care of not using any member after. It is common pattern. [http://stackoverflow.com/questions/2505328/calling-class-method-through-null-class-pointer] – Kamil_H Jul 13 '16 at 13:10
  • 1
    @Kamil_H Are you saying you actually do this in real code? What software do you develop, so as to warn me not to use it. – PaulMcKenzie Jul 13 '16 at 13:16
  • 1
    @Kamil - Using `delete this` can be useful, but only if you have an actual object. – Bo Persson Jul 13 '16 at 13:52
  • @PaulMcKenzie As I said, gmock/gtest does such things. This is where I found it. – Kamil_H Jul 13 '16 at 19:29

3 Answers3

4

Is it gcc bug

No.

or something with c++ code

Yes. You use the arrow operator on a pointer that doesn't point to a valid object. This has undefined behaviour.

Dereferencing null pointer and calling method in this way that does not use any members is fine.

It's not fine according to the standard. It's UB.

What is calling method on pointer?

Is implementation specific.

Deleting this is nothing special.

Deleting this is very special.

You should only take care of not using any member after

Yes, that and you must make sure that only new was used to create all instances on which the function is ever called. No automatic objects, no static objects no new[], no malloc + placement new.

So yes, you can delete this, but be careful.

eerorika
  • 232,697
  • 12
  • 197
  • 326
2

Your intuition here seems to be:

  1. p-> is OK because it is just a syntax for filling in this.
  2. delete this is OK because you don't use this after delete.

But the above may not actually be OK, because dereferencing a null pointer is always undefined behavior. Without optimization enabled this may not cause any trouble, because the compiler is doing a "basic compile" which somewhat matches what you imagine when you "compile in your mind." With optimization, however, GCC will do a lot of things that it normally would not do, such as not bothering to emit "correct" instructions when faced with incorrect source code. There's literally no need for it to do anything at all when you say p-> as your program's first act--it could just pretend main() was empty (or crash, as in your case).

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Drerferencing nullptr - I agree, but deleting nullptr? It is allowed by standard, isn't it? – Kamil_H Jul 18 '16 at 21:35
  • @Kamil_H: You're right, and while I originally didn't think that applied here, on second reading I think it does, so I edited my answer. – John Zwinck Jul 18 '16 at 21:51
0

I know that calling method on nullptr is out of standard, but so far I haven't seen a compiler that wouldn't cope with that in described manner. It seems that gcc6.1 works different (still according to spec). So this is gmock bug. I wonder how many other projects depend on such compiler behavior :)

What is worth to mention is that method is called, 'this' inside is zero as expected and then delete fails. I looked into assembly an there is mov (%rax), %rbx which fails because rax contains zero.

Kamil_H
  • 501
  • 1
  • 5
  • 12