从未初始化的内存中读取每次都会返回不同的答案

时间:2017-09-08 19:00:52

标签: c++ linux facebook linux-kernel initialization

在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"匿名映射,我将其视为“零初始化页面。”

我的问题是:第二次读取怎么可能会返回非零值,导致它们的错误?

1 个答案:

答案 0 :(得分:1)

这些家伙提供的解释完全被打破(至少在给定的背景下)。并且代码具有未定义的行为,无论如何。

如果data指向分配了至少size() + 1大小的块,则由于竞争条件(他之前提到线程的使用),代码具有未定义的行为。

如果data的大小小于({例如,等于size()),则代码具有未定义的行为,因为越界访问(并且竞争条件变得没有实际意义)。