ねむみ高まる

文章力がないので、文章を書く練習をしています。

【C++】no man's land(0xfdfdfdfd)等を変更したときの挙動を見てみた

newの挙動について最近勉強していました。

newしたとき、自分が割り当てた変数以外の様々な値が変更されており???となっていたのですが、 teratailで質問してみたところ、複数の方々より、newの挙動についてご教授頂きました(多謝)。

C++ - newしたときに変更される値について|teratail

VC++のDebug実行では、newしたときメモリの上下に、管理情報としてno man's landという0xfdfdfdfdや確保したバイト数等が割り当てられることを知りました。
そこで、今回はそれらの値を変更してみて、どういった挙動になるかを見てみます。環境はMicrosoft Visual Studio Community 2015、Debug実行で行います。

afterのno man's landを変更

#include <iostream>

using namespace std;

int main()
{
    bool* heapValue;

    heapValue = new bool(true);

    // afterのno man's landを変更する
    *(heapValue + 1) = true;

    delete heapValue;

    return 0;
}

delete heapValueするときにクラッシュし、下記のエラーログが出ました。

HEAP CORRUPTION DETECTED: after Normal block (#150) at 0x0101C178.
CRT detected that the application wrote to memory after end of heap buffer.

afterとなっているので、正しいです。

beforeのno man's landを変更

#include <iostream>

using namespace std;

int main()
{
    bool* heapValue;

    heapValue = new bool(true);

    // beforeのno man's landを変更する
    *(heapValue - 1) = true;

    delete heapValue;

    return 0;
}

delete heapValueするときにクラッシュし、下記のエラー文が出ました。

HEAP CORRUPTION DETECTED: before Normal block (#150) at 0x00E9C170.
CRT detected that the application wrote to memory before start of heap buffer

beforeとなっているので、正しいです。

no man's landを微妙に超えた位置を変更すると?

#include <iostream>

using namespace std;

int main()
{
    bool* heapValue;

    heapValue = new bool(true);

    // no man's landでない範囲外の値を0x00→0x01に変更してみる
    *(heapValue - 5) = true;

    delete heapValue;

    return 0;
}

特に何も言われることなく、実行が無事?成功しました。
無事成功してしまうと、何かしらバグったときに調べるのが大変そうですね。。

バイト数(おそらく)を格納している箇所を1→0に

#include <iostream>

using namespace std;

int main()
{
    bool* heapValue;

    heapValue = new bool(true);

    // メモリのbeforeのno man's landを変更する
    *(heapValue - 12) = 0;

    delete heapValue;

    return 0;
}

メモリ配置は下記です。ここでは0x0132E5D8にheapValueの値が配置され、offset-12した0x0132E5CCの箇所にバイト数が格納されています。

*(heapValue - 12) = 0;を行う前

0x0132E5C0  00 00 00 00 00 00 00 00  
0x0132E5C8  01 00 00 00 01 00 00 00  
0x0132E5D0  96 00 00 00 fd fd fd fd  
0x0132E5D8  01 fd fd fd fd dd dd dd

*(heapValue - 12) = 0;を行った後

0x0132E5C0  00 00 00 00 00 00 00 00  
0x0132E5C8  01 00 00 00 00 00 00 00  
0x0132E5D0  96 00 00 00 fd fd fd fd  
0x0132E5D8  01 fd fd fd fd dd dd dd 

delete heapValueするときにクラッシュし、下記のエラー文が出ました。

HEAP CORRUPTION DETECTED: after Normal block (#150) at 0x0132E5D8.
CRT detected that the application wrote to memory after end of heap buffer.

afterのヒープのメモリが書き換えられているのでは?(意訳)となっており正しくないです。

関係ない話ですが、バイト数は実際の値を見るとoffset-12のところに配置されているっぽいです。しかし、 Win32 Debug CRT Heap Internalsを読んでみるとoffset-16と書いており謎です。仕様が変わったのでしょうか?

参考文献