0

I am trying to debug an optimized version of a program, where an application crashes when I click a button. In the debug version, the application does not crash. I suspect a memory leakage somewhere.

I am not familiar with valgrind, I tried to use it but could not understand the output. I will come back to it later, but I would like initially to see where precisely in the code the crash occurs.

Through adding printouts, I was able to discover that the crash occurs when the last line of the following code is executed.

std::string selected;
int row = 20;
if (objectX == nullptr) 
    std::cout << "objectX is a nullptr" << std::endl;
std::cout << "row count of objectX: " << objectX->rowCount() << std::endl; 
objectX->getAlteredName(row, selected);

Here is the method getAlteredName:

bool getAlteredName (int row, std::string& name) const {
    std::cout << "In getAlteredName function" << std::endl;
    // Do some fancy string stuff here
    return true; 
}

My output is as follows:

row count of objectX: 75

So, that means:

  • objectX is not a nullptr.
  • it is possible to call methods with objectX (e.g. rowCount())

The error occurs with the call to getAlteredName. The std::cout on the first line of the getAlteredName method does not execute. This is what I cannot understand. It is as if the call to getAlteredName itself causes a crash. Why can objectX->rowCount() be called without a problem but merely the call to getAlteredName() causes a crash on the line right after? Could something have happened to cause objectX to become a nullptr between those two lines ? Or maybe there is something else going on that I am missing completely.

I know I do not provide enough information here to find my memory leakage, I just would like an explanation of what are the possible causes of the above behaviour, to give me a few leads for my investigations.

Note that the rowCount() method is declared in the .h file whereas the getAlteredName() method is declared also in the .h file, but as a virtual method. Perhaps this is a clue to the problem.

didjek
  • 393
  • 5
  • 16
  • Most probably you're invoking [Undefined Behavior](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) and any attempts to infer things like "it is possible to call methods with `objectX`" are, strictly speaking, futile. For example, there may be an array-out-of-bounds write somewhere (not necessarily inside `objectX`) which corrupts the memory. It's not a matter of memory leak. Valgrind should help, though, as well as Address Sanitizer. – yeputons May 05 '21 at 08:08
  • Memory leaks very rarely leads to crashes; it's probably the least likely problem. Note that a non-null pointer is not guaranteed to be a valid pointer to an object that exists. Dereferencing an invalid pointer has undefined behaviour but does not necessarily crash or exhibit any other bad behaviour. – molbdnilo May 05 '21 at 08:08
  • Side note: In this particular case, the conclusion "objectX is not a nullptr" is not warranted. Since `objectX` is dereferenced regardless of whether it is `nullptr` or not, the optimizer can deduce that `objectX` cannot be `nullptr`, and so has removed the check `if (objectX == nullptr)` and the statement that prints `objectX is nullptr`. Therefore, you cannot reliably tell from the output alone whether `objectX` was null or not. – j6t May 05 '21 at 10:03

1 Answers1

0

Thanks for the posters above, who set me on the right track. I presumed incorrectly it was a memory leakage issue. However, it was much simpler.

The getAlteredName() method was declared as a virtual method in BaseType.h and I was looking at (and putting std::cout output into) its implementation in BaseType.cc (it probably should not have been implemented there), however, the implementation which my code was calling was in a class which inherited from BaseType (lets call it ChildType). And, in the implementation of getAlteredName in the ChildType class, there was an error.

So advice to anyone in a similar situation: if you are in a class which is inherited elsewhere, check carefully (unlike what I did) in the .h file to see if any methods are virtual ones.

didjek
  • 393
  • 5
  • 16