2017-09-08 5 views
2

Nicholas Ormrod's talkでCppCon 2016で、彼はFacebookで面倒なバグを書きましたが、ここでは初期化されていない(未書き込みの)ページから2バイト2回目の読み取りは最初の読み取り値(ゼロ)とは異なる値(非ゼロ)を返しました。初期化されていないメモリからの読み込みは、毎回異なる回答を返す

彼は、彼らがLinuxで動作していたjemallocI also presumeを使用していると述べました。 jemalloc's manpageは、sbrk()よりも常にmmap()が好きだと言います。

ここで、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"を返します。これは「ゼロ初期化ページ」と読みます。

私の質問は次のとおりです。2番目の読み込みでゼロ以外の値が返され、バグが発生する可能性はありますか?

+0

Nicholasのバグは、ページが条件付きでカーネルに返されたときに発生するので、ページからバイトを読み込むと、カーネルは初期化されていないメモリを返しているので、「0」を返します。しかし、2回目の読み込みでは、読み込みの代わりに*書く*ので、カーネルは実際にメモリが必要であることを認識し、そこに格納されている実際のデータを取得します – Justin

+0

この質問は質問に答えるのに十分なコンテキストを提供しません。それは[mcve]が欠けている。この質問に答えるために、回答者はビデオを見る必要があります – Justin

+0

@ジャスティン私は追加情報のビデオにリンクしましたが、ここでバグのすべての詳細を述べました。 –

答えて

1

この男が提供している説明は、完全に壊れています(少なくとも、特定の状況では)。コードには何があっても定義されていない動作があります。

少なくともsize() + 1サイズで割り当てられたチャンクを指している場合、コードは競合状態のため未定義の動作をしています(前にスレッドの使用が言及されています)。

dataのサイズがそれ未満(たとえば、size()に等しい)の場合、範囲外のアクセス(競合状態が疑いのあるポイントになる)のため、コードには未定義の動作があります。

+0

彼らはFBであらゆる種類のショートカットを作っているようですが、Andrei Alexandrescu(CPP委員会)のような人たちがそのコードに取り組んでいるので、彼らがUBを引き起こしたにもかかわらず、彼らが何をしているのかを知っているのか疑問の恩恵を受ける(そして彼はその話の早い段階で触れている)。だから私は彼の説明を理解し、それを窓の外に投げないようにしようとしている。 –

+0

また、初期化されていないストレージからの読み取りは、それ自体では未定義の動作です。 –

+0

@ YamMarcovicは正しいですが、最初にストレージがどのように初期化されたかわからないので、ストレージが初期化されていないかどうかわかりません。私はあなたのリンクのポイントからビデオを見ました。しかし、正気の前提はそうではないということでしょう。したがって、これは3番目の不確定な動作点です。 – SergeyA

関連する問題