Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Segmentation fault at the end of destructor

I don't know if this question is going to be clear, since I can't give too many details (I'm using a TPL and wrote a huge amount of lines myself). But I'll give it a try.

I am experiencing a segmentation fault which I can't understand. There is a structure (which I didn't design but should be well tested) whose destructor looks like this

Data::~Data()
{
  if(A_ != 0) {
    delete A_;
    A_ = 0;
  }

  if(B_ != 0) {
    delete B_;
    B_ = 0;
  }

  if(C_ != 0) {
    delete C_;
    C_ = 0;
  }
} // HERE

What's bothering me is that, while debugging, I get that the segfault happens at the line marked with 'HERE'. The class Data has only A_, B_ and C_ as dynamically allocated attributes. I also tried to explicitly call the destructor on the other non-dynamic composite attributes, to see if something went wrong during their destruction, but again the segfault happens at the end of the destructor. What kind of errors can give a segfault at that point?.

I hope the question is clear enough, I will add details if needed.

Edit: thanks for the replies. I know it's a scarse piece of code, but the whole library is of course too big (it comes from Trilinos, by the way, but I think the error is not their fault, it must be my mistake in handling their structures. I used short names to keep the problem more compact). Some remarks that somebody asked in the comment replies:

  • about the checks before the delete(s) and the raw pointers: as I said, it's not my choice. I guess it's a double protection in case something goes wrong and A_, B_ or C_ has been already deleted by some other owner of the data structure. The choice raw-pointers vs shared_ptr or other safe/smart pointers is probably due to the fact that this class is almost never used directly but only by an object of class Map that has a pointer to Data. This class Map is implemented in the same library, so they probably chose raw pointers since they knew what they were handling and how.
  • yes, the data structure is shared by all the copies of the same object. In particular, there is a Map class that contains a pointer to a Data object. All the Map's that are copies of one each other, share the same Data. A reference counter keeps track of how many Map's are holding a pointer to the data. The last Map to be destroyed, deletes the data.
  • the reference counter of the Data structure works correctly, I checked it.
  • I am not calling the destructor of this class. It is called automatically by the destructor of an object of class Map that has a pointer to Data as attribute.
  • Data inherits from BaseData, whose (virtual) destructor doesn't do anything, since it's just an interface defining class.
  • It's hard to post the code that reproduce the problem. For many reasons. The error appears only with more than 2 processes (it's an mpi program), and my guess it that a process has some list that is empty and tries to access some element.
  • about the error details. I can give you here the last items in the backtrace of the error during debugging (I apologize for the bad format, but I don't know how to put it nicely):

    1. 0x00007ffff432fba5 in raise (sig=) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64

    2. 0x00007ffff43336b0 in abort () at abort.c:92

    3. 0x00007ffff436965b in __libc_message (do_abort=, fmt=) at ../sysdeps/unix/sysv/linux/libc_fatal.c:189

    4. 0x00007ffff43736d6 in malloc_printerr (action=3, str=0x7ffff4447780 "free(): corrupted unsorted chunks", ptr=) at malloc.c:6283

    5. 0x00007ffff4379ea3 in __libc_free (mem=) at malloc.c:3738

    6. 0x0000000000c21f71 in Epetra_BlockMapData::~Epetra_BlockMapData ( this=0x1461690, __in_chrg=) at /home/bartgol/LifeV/trilinos/trilinos-10.6.4-src/packages/epetra/src/Epetra_BlockMapData.cpp:110

To conclude, let me restate my doubt: what kind of errors can appear AT THE END of the destructor, even if ALL the attributes have been deleted already? Thanks again!

like image 807
bartgol Avatar asked Jul 30 '12 17:07

bartgol


People also ask

How do you fix segmentation fault in C++?

See if your compiler or library can be set to check bounds on [i] , at least in debug mode. Segmentation faults can be caused by buffer overruns that write garbage over perfectly good pointers. Doing those things will considerably reduce the likelihood of segmentation faults and other memory problems.

Where does segmentation fault occur?

A segfault occurs when a reference to a variable falls outside the segment where that variable resides, or when a write is attempted to a location that is in a read-only segment.

What is segmentation fault with example?

A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system).


2 Answers

One problem that can cause a segfault at a function exit is heap or stack corruption.

It is possible that some other part of your program is causing problems. Something like double-destruction, or buffer overrun can cause memory corruption.

Often, debug builds of programs will include a check at function exit to ensure that the stack is intact. If it's not, well, you see the results.

like image 76
Anthony Avatar answered Sep 27 '22 18:09

Anthony


When the explicit body of the class destructor completes, it proceeds to perform some implicit actions: it calls base class and member destructors (in case you have base classes and members with non-trivial destructors) and, if necessary, it calls raw memory deallocation function operator delete (yes, in a typical implementation operator delete is actually called from inside the destructor). One of these two implicit processes caused the crash in your case, apparently. There's no way to say precisely without more information.

P.S. Stylistically the code is awful. Why are they checking for null before doing delete? What is the point of nulling deleted pointers in the destructor?

like image 27
AnT Avatar answered Sep 27 '22 17:09

AnT