5 ms·
Unique_ptr difference between libstdc++ and Libc++ crashes your application
- eklitzke 6y agoI'm not sure what the author expected when trying to link code that mixes uses of libstdc++ and libc++: there are not ABI compatible in any way. If you need ABI compatibility between different compilers you must write C.
- beached_whale 6y agoThis isn't even compilers. clang is perfectly happy using other peoples std library implementations(well libstdc++ and MS STL's that I know of so far). I think it is more apt to say that you do not mix libraries with the same names here, or in this case don't mix std library implementations.
- josefx 6y agoI am not sure it is about mixing implementations, just that it crashes with one and not the other. One implementation runs the destructor and then sets the pointer to null -> when code invoked by the destructor accesses the pointer everything still works. The other implementation sets the pointer to null and then runs the destructor -> when code invoked by the destructor accesses the pointer it gets a null.
- ogoffart 6y agoFrom what I understand, this is not about mixing uses of different libraries. This is about a program that works fine with libstdc++, but crashes with libc++ because of a different behavior between the two: the order in which the destructor is called and the unique_ptr set to 0.
- hallarempt 6y agoI'm not sure how you could come to that conclusion? The problem is that the same code compiled on two different platforms with two different compilers and two different stdlib implementations crashes on one of those, and not on the other.
- formerly_proven 6y agoI'm not sure where you read the author linked libstdc++ and libc++ into the same application? The post notes a crash caused by these two implementations behaving slightly differently, which has nothing to do with ABI compatibility.
- jeffbee 6y agoThe correct headline here is “KDE defect is silent with libstdc++, fatal with libc++”.
- fefe23 6y agoCame here to say that. Also note that with libstdc++ that bug is actually a use-after-free bug, which has grave security implications on top of being a regular old bug.
- Arainach 6y agoIt's not use-after-free - the object is in the process of being destroyed, the memory hasn't been released yet. This just has to do with the value of the "this" pointer.
- armada651 6y agoThe question is, why would KDE need the pointer value after the referenced object is destroyed? That implies a use-after-free.
- varajelle 6y agoBig applications can be complicated and have some complex states. A destructor calls a function that calls a function that checks if an object exist. By chance with libstdc++, the half destroyed object was marked as "non existent", but not with libc++. Destructor usually call function to unregister themselves from some other places, or free other owned ressources.
- ttt0 6y agoThey don't. If I understand it correctly, destroying the object triggers the QEvent::Destroy event, which then goes through the event handler on the parent object that might access that pointer. On libc++ that pointer is set to null before calling the destructor and triggering the event, so it's null pointer dereference. The object is accessed only through the unique_ptr, so unless multithreading is going on, I don't think there is a way to have use-after-free. You might be potentially accessing garbage, but it's not use-after-free. Aside, using a pointer to an object that is destroyed is not always use-after-free. Accessing the value might happen during the destruction, which is the case here or the object can be destroyed, but the memory is not released. "Placement new" and stuff.
- Someone 6y agoSo, is either of these not standard-compliant? I Looked at https://en.cppreference.com/w/cpp/memory/unique_ptr https://en.cppreference.com/w/cpp/memory/unique_ptr (yes, I know that’s not the standard, but _I_ trust it to follow it close enough), and couldn’t find evidence for it. I suspect, however, that the standards committee, knowing of this discrepancy, would go with libc++. They explicitly said that reset has to update the pointer before deleting the old object (https://en.cppreference.com/w/cpp/memory/unique_ptr/reset https://en.cppreference.com/w/cpp/memory/unique_ptr/reset), so one would think they don’t want get() to return the pointer while the unique_pointer destructor is running. On the other hand, none of that matters in the case if multiple threads or out-of-order CPUs (or do I read https://en.cppreference.com/w/cpp/memory/unique_ptr/reset https://en.cppreference.com/w/cpp/memory/unique_ptr/reset incorrectly, and is some sort of fence implied there?)
- inetknght 6y agounique_ptr does not have an implied fence. atomic<unique_ptr> is what you need if you need a fence. many might argue for shared_ptr but, while it does have a fence, it does _not_ have the same semantics as unique_ptr i don't think the problem is libc++ or libstdc++. the problem is, indeed, that KDE is using the unique_ptr after and/or during its lifetime expiration. the immediate fix is indeed as patched, but a better fix would be better management of object lifetimes. good luck getting that done in anything using Qt though
- anderskaseorg 6y agoThe libstdc++ and libc++ destructors are both standard-compliant (as would be a destructor that doesn’t null the pointer at all) because any program that attempts to observe the difference is wrong. See https://stackoverflow.com/a/66295139/115030 https://stackoverflow.com/a/66295139/115030, https://cplusplus.github.io/LWG/issue2224 https://cplusplus.github.io/LWG/issue2224.