tags:

views:

72

answers:

4

Suppose I have a class like

class A {
    int x;
    int y;
  public:
    getSum1() const {
        return getx() + y;
    }
    getSum2() const {
        return y + getx();
    }
    getx() const {
        return x;
    }
}

And then I have

int main(int argc, char **argv) {
    A *a = 0;
    switch(argc) {
    case 0:
        a->getsum1();
        break;
    default:
        a->getsum2();
        break;
    }
    return 1;
}

This program will segfault. I noticed that on my machine, when getsum1 executes, the core dump says the segfault was caused in getx, and when getsum2 executes it says the fault happened in getsum2.

This makes sense. I have 2 questions:
1. is this behaviour specified, or is it implementation dependent?
And most importantly:
2. Could the core dump say that the segfault happened in main, when a was dereferenced? (i.e. at a->getsum*)

Thanks.

A: 

Calling accessing members and calling member functions on null pointers is undefined behaviour.

The segfault happens when the program tries to access x or y, which is why it happens in getx() in the first one and getSum2() in the second.

Peter Alexander
+1  A: 

When you called those functions on a null pointer, you got undefined behavior. That's really all that should be said; anything can happen, don't do it.

The reason it segfaults is because there is no A at null. Attempting to access those members is attempting to access an invalid address. (This happens in getx and getSum2, hence the segfault report.)

No, it cannot say the segfault happened in main because null wasn't accessed in main. (You still entered undefined behavior in main, no doubt, but in practice it just called a function with this set to null.) You accessed it in those functions. In practice, if a function never uses this, it won't crash with a null pointer.

But don't.

GMan
If a function doesn't use `this` then it should be `static` anyway.
Peter Alexander
@ Peter Alexander: Technically yes it can be a static weather it should would depend very much on context. Personally I hate having absolute rules programming is so much about current situations that having hard and fast rules makes the code ugly. So I would say a method that does not use any members should be put into consideration (very high on the list) for being made into a static method.
Martin York
A: 

By the time the coredump is happening you're not really in C++ anymore. Some statements in the compiled code caused bad things to happen, such as attempting to access an invalid memory address, in your case via a null pointer.

I guess that you're hoping that the diagnostics in the core dump might pin-point the problem rather than (seemingly in this case) giving slightly indeterminate results.

The thing is that going back from compiled binarys to lines of source is somewhat tricky because there's plenbty of scope in the language for some "as-if" kind of reordering of statements and other cleverness.

So, C++ itself, in the language spec, won't specify what the core dump will tell you, and as has already been observed explicitly gives underfined behaviours when de-referencing null pointers.

The thing is I don't really think this matters too much. For this kind of error getting a "close-enough" indictor of where the problem is soon leads to the source of the problem. Far nastier are the heap corruption problems that occur where symptom and cause can be many steps remote from each other and core dumps are less use.

djna
A: 
dreamlax