在Nicholas Ormrod's talk在 CppCon 2016 上,他提到了 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"对于匿名映射,我将其读作“零初始化页面”。
我的问题是:第二次读取怎么可能返回非零值,从而导致他们的错误?
最佳答案
无论这些人提供的任何解释都是完全错误的(至少,在给定的上下文中)。无论如何,代码都有未定义的行为。
如果 data
指向分配了至少 size()
+ 1 大小的 block ,则由于竞争条件,代码具有未定义的行为(他提到了用法之前的线程)。
如果 data
的大小小于该值(例如,等于 size()
),则代码具有未定义的行为,因为越界访问(并且竞争条件成为一个有争议的点)。
关于c++ - 从未初始化的内存中读取每次都会返回不同的答案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46123029/