Summary: | std::map::operator[] crashes with std::vector of objects used as key | ||
---|---|---|---|
Product: | gcc | Reporter: | Kevin Harer <kevin_harer> |
Component: | libstdc++ | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED INVALID | ||
Severity: | normal | CC: | daniel.kruegler |
Priority: | P3 | ||
Version: | 4.1.2 | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | ||
Attachments: | The main.ii file to reproduce the problem |
Description
Kevin Harer
2016-07-06 17:06:30 UTC
I can reproduce the problem for gcc versions smaller than 4.7.3, but I doubt that these old versions will be maintained for a fix. (In reply to Daniel Krügler from comment #1) > I can reproduce the problem for gcc versions smaller than 4.7.3, but I doubt > that these old versions will be maintained for a fix. Daniel I sort of thought that - There is several acceptable work-arounds. I just wanted to report it so it gets fixed wherever you can fix it - Also - depending on the fix, I am not above hacking our own version of headers... bool Small::operator<(const Small &rhs) const { if (_field1 < rhs._field1) return(true); if (_field2 < rhs._field2) return(true); if (_field3 < rhs._field3) return(true); return(false); } This is not a valid StrictWeakOrdering, so it's undefined behaviour to put those objects into a std::map. This is a bug in your code, not GCC. Consider: #include <cassert> class Small { public: Small() {} ~Small() {} bool operator<(const Small &rhs) const; int _field1; int _field2; int _field3; }; bool Small::operator<(const Small &rhs) const { if (_field1 < rhs._field1) return(true); if (_field2 < rhs._field2) return(true); if (_field3 < rhs._field3) return(true); return(false); } int main() { Small a, b; a._field1 = 1; a._field2 = 2; a._field3 = 0; b._field1 = 2; b._field2 = 1; b._field3 = 0; assert( ! ((a < b) && (b < a)) ); } The assertion fails. https://www.sgi.com/tech/stl/StrictWeakOrdering.html N.B. it doesn't matter that you're using map<vector<Small>, int> rather than map<Small, int> directly, because the comparisons on the vector use the comparisons on the Small type, so an invalid ordering for Small produces an invalid ordering for SmallVec too. This still fails: std::vector<Small> va(1, a), vb(1, b); assert( ! ((va < vb) && (vb < va)) ); Well darn. You are right. I am sorry for wasting your time - but glad that I did, in that the error will come out in my application in some other worse way - Thank you for your time - |