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

问题描述 投票:0回答:2

Nicholas Ormrod 在 CppCon 2016 的演讲中,他提到了 Facebook 的一个阴险的错误,即从未初始化(未写入)的页面读取单个字节两次,因此在某些情况下第二次读取返回一个(非零) )值与第一次读取的值(零)不同。

他提到他们使用了jemalloc,并且我也推测他们在Linux上运行。 jemalloc 的手册页说它总是更喜欢

mmap()
而不是
sbrk()

现在,jemalloc 唯一的

mmap()
调用 使用标志
MAP_PRIVATE | MAP_ANONYMOUS
,偶尔包含
MAP_FIXED
,特别是它不使用
MAP_UNINITIALIZED
。这意味着页面在分配时总是零初始化

此外,对于匿名映射,即使

madvise()
MADV_DONTNEED
也会返回 “零填充按需页面”,我将其理解为“零初始化页面”。

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

c++ linux facebook linux-kernel initialization
2个回答
1
投票

无论这些人提供什么解释都是完全错误的(至少在给定的上下文中)。无论如何,代码都有未定义的行为。

如果

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

如果

data
的大小小于该值(例如,等于
size()
),则由于越界访问,代码具有未定义的行为(并且竞争条件成为有争议的点)。


0
投票
if (data[size] != '\0')
  data[size] = '\0';

这很简单,因为在第一次写入之前,它总是尝试读取它,而

data[size]
仍未初始化,因为
\0
是懒惰地写入FB字符串中的

© www.soinside.com 2019 - 2024. All rights reserved.