1. ホーム
  2. c

[解決済み] mallocの結果をキャストすることの何が危険なのでしょうか?

2023-03-17 02:54:52

質問

さて、人々がこれをdupとマークし始める前に、私は以下のものをすべて読みました、どれも私が探している答えを提供していません。

  1. C FAQ。mallocの戻り値をキャストするのは何が問題なのですか?
  2. SOです。malloc()の戻り値を明示的にキャストすべきでしょうか?
  3. SOです。C 言語における不要なポインタキャスト
  4. SOです。malloc の結果をキャストするのですか?

C FAQと上記の質問に対する多くの回答の両方が、キャストすることによる謎のエラーを引用しています。 malloc の戻り値をキャストすることで隠せるという不思議なエラーを挙げていますが、実際にはそのようなエラーの具体的な例はありません。 さて、私が言ったことに注目してください。 エラー ではなく 警告 .

さて、次のようなコードが与えられました。

#include <string.h>
#include <stdio.h>
// #include <stdlib.h>

int main(int argc, char** argv) {

    char * p = /*(char*)*/malloc(10);
    strcpy(p, "hello");
    printf("%s\n", p);

    return 0;
}

上記のコードを gcc 4.2 でコンパイルすると、キャストの有無にかかわらず同じ警告が表示され、プログラムはどちらの場合も適切に実行され、同じ結果が得られます。

anon@anon:~/$ gcc -Wextra nostdlib_malloc.c -o nostdlib_malloc
nostdlib_malloc.c: In function ‘main’:
nostdlib_malloc.c:7: warning: incompatible implicit declaration of built-in function ‘malloc’
anon@anon:~/$ ./nostdlib_malloc 
hello

というわけで、キャスティングが原因で発生する可能性のあるコンパイルエラーやランタイムエラーの具体的なコード例をどなたか教えていただけませんか? malloc の戻り値をキャストすることで発生する可能性のある、コンパイルや実行時のエラーの具体的なコード例をどなたか教えてください。

編集 この問題に関して、私は2つのよくできた議論に出会いました。

  1. キャスティングを支持する。CERT アドバイザリ。 メモリ割り当て関数呼び出しの結果を、割り当てられた型へのポインタに即座にキャストしてください。
  2. キャストに対して (2012-02-14現在、404エラー) インターネット・アーカイブ・ウェイバック・マシン からのコピー 2010-01-27.{2016-03-18:"Page cannot be crawled or display due to robots.txt."})

どのように解決するのですか?

を取得することはできません。 コンパイラーエラー というエラーは出ませんが コンパイラ警告 . あなたが引用したソースが言っているように(特に 最初のもの ) 、あなたは ができる は、予測できない ランタイムエラー キャストを使用した場合 を含まずに stdlib.h .

つまり、あなた側のエラーはキャストではなく、インクルードし忘れている stdlib.h . コンパイラは malloc を返す関数であると仮定します。 int を返す関数であり、したがって void* が実際に返すポインタを mallocint に変換され、その後、明示的なキャストによりポインタ型に変換されます。いくつかのプラットフォームでは int とポインタは異なるバイト数を取ることがあるので、型変換はデータ破損につながる可能性があります。

幸いなことに、最近のコンパイラーは実際のエラーを指し示す警告を出します。以下の gcc の出力を見てください。これは 暗黙の 宣言 ( int malloc(int) ) は、組み込みの malloc . そのため gcc は知っているようです。 malloc がなくても stdlib.h .

このエラーを防ぐためにキャストを省くことは、ほとんど次のように書くのと同じ理由です。

if (0 == my_var)

の代わりに

if (my_var == 0)

を混同してしまうと重大なバグを引き起こす可能性があるため、後者は === であるのに対し、前者はコンパイルエラーになります。個人的には、後者のスタイルの方が私の意図をよく反映しているし、このような間違いをすることはあまりないので、後者のスタイルを好んでいます。

によって返される値をキャストする場合にも同じことが言えます。 malloc : 私はプログラミングにおいて明示的であることを好みますし、一般的に、使用するすべての関数のヘッダーファイルをインクルードするようダブルチェックします。