Author Options:

Why would an empty std::map seg fault on the first insert? Answered

I've got a weird C++ problem which make no sense to me.  I have a class containing a std::map<> data member, which I fill during the initialization process.  On my Mac (OSX 10.5.8, GCC 4.0.1), the map is filled perfectly fine, and the data is accessed when the job runs with no problem.  When I build and run on Linux (RHEL 5.6, GCC 4.1.2), the std::map<> itself seg-faults the first time something is inserted.

I've tried the insert with both table[key] = value and with table.insert(std::pair<>(key,value)) and I get the identical result. For some reason, std::map<>::insert_unique() doesn't recognize that the map is empty, and it tries to decrement one position before begin(), triggering the seg-fault.

Am I doing something wrong? Do I need to explicitly zero the map (the constructor should do that itself, shouldn't it?)?



Best Answer 6 years ago

I had a similar situation with std:set. Looking at the assembler output from the compiler, mine was a compiler bug. The compiler used the wrong offset to access a member variable a few functions deep. You might try a newer version of gcc.

Is the insert happening immediately after the map's creation?

If not, I'd suspect a wild pointer problem somewhere, overwriting the map...

Yes, immediately (the map is in a static class that gets instantiated on the first request for insert). I thought about pointer corruption myself, but when I print the newly created map in GDB, it shows the proper empty state.

My C++ skills are limited (last time I used it intensively was before the std:: library was created!), so I'm probably going to have to bow out. Good luck.

(Sanity check: You aren't doing something odd like using a placement constructor, right?)

I'm not using a placement constructor, but I was instantiating a static instance of the wrapper class. I don't know why, but when I replaced the static instance with a static class function containing a static object, the Linux (GCC 4.1.2) build worked properly. Sigh...

Ah, "Properly" = "as I expected" != "what the standard probably says".......

Personally, I think C++ is a horrible language, but that's just me.


I agree that C++ is a "horrible language," but it is what we use in HEP, and it does have some nice features (polymorphism and inheritance, for example). Be grateful we aren't still using FORTRAN!

By "properly," I mean that a data object declared as a static member of a class should have job-execution scope and should not be deleted and recreated in the midst of a job. The identical code compiled under GCC 4.0.1 on my Mac behaved that way, but with GCC 4.1.2 on a Linux server did not.

Even Fortran's gone OOP in the lastest versions AFAIK.


Yes, indeed. There's FORTRAN 90 and its successors, which include some OOP features.

Most of high-energy physics uses C++. It was generally adopted in the early 1990's, when there were few good options for object-oriented languages which also had strong mathematical support, as well as an easy way to interface with FORTRAN. The major simulation toolkit used throughout HEP, GEANT4, is written in C++.

I don't see why the constructor should necessarily initialise the map. What happens if you try zeroing it ?

How do you instantiate the map in the code ?


Well, the STL documentation says that the ctor creates an empty map. One piece of weirdness is that if I do explicity clear() the map in the class ctor, the insert works fine.

I think it depends on the exact syntax when its instantiated.

True. I'm using the default (no argument) ctor, which, as in your documentation, claims, "default constructor. Constructs empty container."