简体   繁体   中英

Strange crash of Qt 4.8.4 QList under Apple LLVM

Does anybody know why this code crashes?

Code that crashes:

QList<int> lst;
const auto& tmp = QList<int>() << 1;
lst = tmp;

Code that works (tmp is not a reference):

QList<int> lst;
const auto tmp = QList<int>() << 1;
lst = tmp;

Compiler:

Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix 

Crash message:

qt_test(76726,0x7fff76257180) malloc: *** error for object 0x101208b60: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
qt_test: line 43: 76726 Abort trap: 6           $DBG_TEST "$@"

This message appears when 'lst' destructor called.

Under VisualStudio 2012 this code works well.

After thinking about this more, I finally noticed the glaring inconsistency.

QList<int> lst;
const auto& tmp = QList<int>() << 1;
lst = tmp;

Specifically, looking at this line:

const auto& tmp = QList<int>() << 1;

QList<int>() is a temporary. This temporary is being passed into QList<int>::operator<<(...) , which is then returning it back as a reference. The problem here is the level of indirection; if you tried to store QList<int>() into a const-reference, it should live until the const-reference fell out of scope. But that reference was instead passed to an operator as this , and is lost by the end of the statement.

Why this works in Visual Studio and not GCC is questionable. A quick Google for answers turns up at least one interesting result where it points to the following clauses in the standard:

If the initializer expression is an rvalue, with T2 a class type, and “cv1 T1″ is reference-compatible with “cv2 T2,” the reference is bound in one of the following ways (the choice is implementation defined):

The reference is bound to the object represented by the rvalue or to a subobject with that object

A temporary of type “cv1 T2″ is created, and a constructor is called to copy the entire rvalue object into the temporary. This reference is bound to the temporary or to a subobject with the temporary.

So, it looks like Visual Studio is taking the second approach, which happens to make a difference in this edge case, since the value will be copied in the statement anyways. It really does put into question the usefulness of a const-reference, though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM