在CppCon 2016的Nicholas Ormrod's talk中,他提到Facebook上的一个阴险的错误,其中从未初始化(未写入)页面读取了一个字节,两次,这样有时第二次读取返回的情况(非零)值与第一个读数的值(零)不同。
他提到他们使用 jemalloc ,而I also presume他们在Linux上运行。 jemalloc's manpage表示它总是优先mmap()
而不是sbrk()
。
现在,jemalloc's only mmap()
call使用标记MAP_PRIVATE | MAP_ANONYMOUS
,偶尔包含MAP_FIXED
,特别是它不使用MAP_UNINITIALIZED
。这意味着分配时页面为always zero-initialized。
此外,对于匿名映射,即使madvise()
with MADV_DONTNEED
也会返回"zero-fill-on-demand pages"匿名映射,我将其视为“零初始化页面。”
我的问题是:第二次读取怎么可能会返回非零值,导致它们的错误?
答案 0 :(得分:1)
这些家伙提供的解释完全被打破(至少在给定的背景下)。并且代码具有未定义的行为,无论如何。
如果data
指向分配了至少size()
+ 1大小的块,则由于竞争条件(他之前提到线程的使用),代码具有未定义的行为。
如果data
的大小小于({例如,等于size()
),则代码具有未定义的行为,因为越界访问(并且竞争条件变得没有实际意义)。