linux c開発:malloc(0)について

1859 ワード

1つのバグがmalloc(0)に植えられているので、記録する必要があります.結論を先に言います.
  • malloc(0)は許可され、少なくとも私が働いているlinuxシステムではそうであるNULL以外のポインタを返します.manドキュメントには、malloc()allocates size bytes and returns a pointer to the allocated memory.The memory is not cleared. If size is 0,then malloc()returns either NULL,or a unique pointer value that can later be successfully passed to free()キーはこのorにあり、NULLを返す場合があるかもしれないが、NULLでない場合を無視することはできない.私のバグはこの間違いを犯したのです.
  • 実際のmalloc(0)は意味がなく、パラメータ値を判断すべきであり、0であればmallocを必要とせずNULLポインタを返し、size_tパラメータとmallocの戻り結果が統一され、この詳細が分からない人、例えば前の私がバグを書くことを避けます.

  • 私のバグを見てみると、私はこのような関数を書いたのではないでしょうか.
    uint8_t generate_random_buffer(char **out_buf)
    {
        uint8_t size = get_random_byte();
        *out_buf = malloc(size);
        set_randombytes_buf(*out_buf, size);
        return size;
    }
    

    この関数は、size、mallocのbufとして0~255のunsigned byteをランダムに出力し、ランダムバイトを入力します.その後、パラメータによってbufを呼び出し元に戻し、関数はbufのsizeを返します.ランダムに出てきたsizeが0かもしれないことを知っていて、malloc(0)も調べても大丈夫で、NULLを返すかもしれません.そして私は油断しました.この関数を呼び出す場所で、このランダムbufを使用した後、私は彼を解放する必要があります.直接使います!=NULLは判断し,関連するbufを解放した.その関連bufはsizeが0より大きいとmallocが出てくるが、sizeが0に等しい場合、この関連bufのポインタはスタック上の構造体を指す.まあ、この状況は少し複雑ですが、結局は実際のプロジェクトです.バグの元は戻るsizeが0の時、私はmallocという関連bufを持っていません.この関連bufを解放する条件はランダムbufがNULLではありません.私はこのように書くのはただ怠けるためで、判断を少なくして、その時、sizeが0より大きい時にランダムbufがNULLではないと思っていました.だから関連bufもmallocが過ぎたのです.実際、sizeが0の場合、ランダムbufのポインタはNULLではなく、私がランダムbufがNULLではないと判断したときにfreeをついでに関連bufを持ってdouble freeのcrash(実はfreeスタック上のオブジェクト)をもたらしたことがわかりました.バグを解決する方法は、返されるsize値とランダムbufポインタを区別することができますが、特に他の人が私が書いた関数を使っている場合は似たような問題を起こさないほうがいいと思いますので、sizeが0の場合mallocをしないように変更しました.これはランダムbufを保持するポインタがNULLです.
    uint8_t generate_random_buffer(char **out_buf)
    {
        uint8_t size = get_random_byte();
        if(size > 0) {
            *out_buf = malloc(size);
            set_randombytes_buf(*out_buf, size);
        }
        return size;
    }