[cfe-dev] once_flag assumes zero-initialized memory
Gordon Henriksen
gordonhenriksen at me.com
Thu Dec 20 18:23:30 PST 2012
libc++'s std::once_flag does not function if it is not initialized in zero-initialized memory. Please find a test attached. The C++11 standard specifically calls out dynamic allocation of once_flag in this example from §30.4.4.2:
// object flag, member function
class information {
std::once_flag verified;
void verifier();
public:
void verify() { std::call_once(verified,verifier); }
};
Here's a short example of the nonconforming behavior:
$ cat call_once-dynamic.cpp
#include <mutex>
#include <type_traits>
#include <cassert>
int main() {
std::aligned_storage<sizeof(std::once_flag),
alignof(std::once_flag)>::type buffer;
memset(&buffer, 0xff, sizeof(buffer));
std::once_flag *flag = new ((void *) &buffer) std::once_flag;
bool called = false;
std::call_once(*flag, [&called]{ called = true; });
assert(called && "once_flag is incompatible with dynamic allocation!");
flag->~once_flag();
}
$ cat Makefile
CXX = xcrun clang++
CXXFLAGS = -std=c++11 -stdlib=libc++
.PHONY: execute-test
execute-test: call_once-dynamic
@if ./call_once-dynamic; then echo pass; else echo fail; fi
call_once-dynamic: call_once-dynamic.cpp
xcrun clang++ -std=c++11 -stdlib=libc++ -o $@ $<
$ make
xcrun clang++ -std=c++11 -stdlib=libc++ -o call_once-dynamic call_once-dynamic.cpp
Assertion failed: (called && "once_flag is incompatible with dynamic allocation!"), function main, file call_once-dynamic.cpp, line 13.
/bin/sh: line 1: 45638 Abort trap: 6 ./call_once-dynamic
fail
For users, a workaround is as follows. I think this covers most core use cases, but isn't a perfect replacement for std::once_flag.
class once_flag_libcpp_hack : public std::once_flag {
public:
once_flag_libcpp_hack() {
memset(static_cast<std::once_flag*>(this), 0, sizeof(std::once_flag));
}
};
namespace mycorp { typedef once_flag_libcpp_hack once_flag; }
— Gordon
-------------- next part --------------
A non-text attachment was scrubbed...
Name: call_once-dynamic.cpp
Type: application/octet-stream
Size: 484 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20121220/8a30207f/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Makefile
Type: application/octet-stream
Size: 264 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20121220/8a30207f/attachment-0001.obj>
More information about the cfe-dev
mailing list