4

自分のコードの多くが c99 規則に違反していて、未定義の動作につながっていることに気がついた最後の数日/数週間の不安から、私は ISO/IEC 9899:TC3 ドラフト ペーパーを明示的に読み始めました。特に、付録「J.2 未定義の動作」は、これらの規則に違反するコードをコンパイルするのが難しい理由のほとんどが論理的であり、場合によっては、少なくとも「まあ、わかりません。それの何が問題なんだ、でも私はそのように「しなければならない」」しかし、1つのポイントがあります...

「要求されたサイズがゼロの calloc、malloc、または realloc 関数の呼び出しによって返された null 以外のポインターが、オブジェクトへのアクセスに使用されます (7.20.3)。」

(ISO/IEC 9899:TC3 の「J.2 未定義の動作」を読んでいないすべての人のために、このセクションでは未定義の動作が発生するケースについて説明します)。

そのため、その事件について頭の中で非常に多くの質問があります。

初めに:

サイズがゼロのメモリ ブロックを割り当てる必要があるのはなぜですか?

そして、そのようなブロックを手に入れたら、それで何ができますか?

未定義の動作を回避する目的で、おそらく、それが指しているメモリにアクセスしたくない...

だから私はもう少し調査をしました....いくつかの異なるmalloc()マニュアルページを探しました。そして Linux malloc(3) man で見つけました:

「サイズが 0 の場合、malloc() は NULL を返すか、後で free() に正常に渡すことができる一意のポインター値を返します。」

これが私を助けた唯一のことは、あなたと私自身に追加の質問があったことです。同じ条件で同じパラメーターを使用した関数呼び出しが異なる結果を返す可能性がある場合は、想像するのはそれほど難しいことではありません。要求されたサイズがゼロのブロックへの null 以外のポインターは、望ましくない副作用である可能性があります。これはどういう意味ですか

if ((void *ptr = malloc (0)) == NULL)
{
    /*...*/
}

これじゃ足りない?このような *alloc 呼び出しを処理する必要がありますか?

if (X <= 0)
{
    if ((*ptr = malloc (X)) != NULL)
    {
        exit (*);
    }
    else
    {
        /*...*/
    }
}
else
{
    if ((*ptr = malloc (X)) == NULL)
    {
        /*...*/
    }
}

しかし、たとえそれが予想されたとしても、そのような

「後で free() に正常に渡すことができる一意のポインター値」

、それを扱う方法は?私はそれを変更することができました...私はそれを解放することさえ許されています(ところで、他のすべての割り当てられたメモリでも行う必要があるように、解放する必要があるということですか、それともあなたが許可されているだけですか?コードフローを壊さないでください

このようなポインターを作成するだけの違いは何ですか?

void *X = (void *)"1234abc";

誰かがその科学の哲学について私を助けてくれることを願っています.

4

3 に答える 3

3

C はサイズがゼロのオブジェクトをサポートしていませんが、 への引数malloc()は 型size_tであり、プログラムが を呼び出さないようにする良い方法はありませんmalloc(0)。それはプログラマーの意図ではないかもしれませんが、必ずしも文字通りではありませんmalloc(0)。である可能性が高くmalloc(count)countは何らかの計算の結果です。

標準で 2 つの異なる動作が許可されているのは、単純に、既存の実装 (元の標準が作成された時点) が異なることを行ったためであり、作成者は既存のコードを壊さないようにしたかったからです。そのようなコードは間違いなくすでに壊れているか、少なくとも移植性がありませんでしたが、いずれかの動作を許可することで、どのように動作するかについて仮定を行ったプログラムは、それが書かれたシステムで動作しmalloc(0)続けることができました.

首尾一貫した説明を探している場合、それを見つけることはできません。C が今日ゼロから設計されていた場合、malloc(0)ほぼ確実に の動作は何らかの形で突き止められていたでしょう。それか、動作が未定義になっていたでしょうが、実装定義にするということは、コードが にゼロを渡していないことをそれほど注意深くチェックする必要がないことを意味しますmalloc()

実際、委員会の決定はC99 Rationaleのセクション 7.20.3、160-161 ページに文書化されています。

それは次のことを意味します。

void *ptr = malloc(0);
free(ptr);

正しく動作します。free()引数が null ポインターの場合は何もしません。

の結果で何ができますmalloc(0)か? 成功するmalloc(1024)と、割り当てられたスペースに 1024 バイトを格納できます。によって割り当てられたスペースにバイトを格納することはできませんmalloc(0)-- これはまさにあなたが求めていたものです。

于 2013-08-08T17:42:00.077 に答える
0

次のように、コードをより明示的にすることができます。

if (X <= 0)
{
    ptr = NULL;
}
else
{
    ptr = malloc(X);
    if (ptr == NULL)
    {
        /*...*/
    }
}

これは次のように蒸留できます。

 ptr = (X <= 0) ? NULL : malloc(X);
 if (ptr == NULL) { /* ... */}

今日、C ではmalloc、要求されたストレージを取得できない場合、NULL を返します。また、このコードは問題を完全に回避し、さらに重要なことに潜在的な落とし穴を回避します。

于 2013-08-09T01:55:02.147 に答える