5

私はあなたがナックルで私をラップすることを知っていますが。

セグメンテーション違反になるのはなぜですか

char* cmd;
strcpy(cmd, argv[0]);

これがないとき

char *cmd;
cmd = "plop";

しばらく練習していなかったので、その理由が思い出せません。

ps:実際、strcpyの前にそのようなものが良いことを私は知っています

char *cmd = (char*) malloc(strlen(argv[0]));

しかし、なぜこのセグメンテーション違反が発生するのか疑問に思っています。

ありがとう !

4

4 に答える 4

10

あなたがするとき:

char * cmd;

スタックにポインタを割り当てています。このポインタは、意味のある値に初期化されていません。

次に、これを行うと:

strcpy(cmd, argv[0]);

argv[0]に含まれている文字列を、が指すアドレスにコピーしますcmd。これは...意味がありません。あなたは幸運なので、それは単にsegfaultsです。

これを行うとき:

cmd = "plop";

静的に割り当てcmdられた文字列定数のアドレスに割り当てます。このような文字列は読み取り専用であるため、それらへの書き込みは未定義の動作です。

それで、これをどのように解決するのですか?書き込み先のランタイムにメモリを割り当てます。2つの方法があります:

1つ目は、次のようにスタックにデータを割り当てることです。

char cmd[100]; // for instance

charこれにより、スタックに100秒の配列が割り当てられます。ただし、必要なメモリの量を事前に知っておく必要があるため、必ずしも堅牢であるとは限りません。スタックもヒープよりも小さいです。これにより、オプション番号2が表示されます。

char *cmd = malloc(whatever_you_need); // no need to cast, by the way, unless you're in C++

whatever_you_need charこれにより、ヒープにsが割り当てられます。free使い終わったら、メモリを解放することを忘れないでください。

于 2011-06-22T23:42:17.660 に答える
5

あなたはセグメントを取得します。cmd最初の例では何も指していません(つまり、未定義のものを指しているため、ポインタから文字を読み取ったり、ポインタに文字を書き込んだりしようとすると、アクセス違反が発生する可能性があります)

2番目の例では、正当な文字列を指すようにcmdを設定しています。

于 2011-06-22T23:34:54.573 に答える
4

argv [0]のコピーを簡単に作成したい場合は、

char* cmd = strdup(argv[0]);

もちろん、strdupの結果がnullかどうかを確認することをお勧めします。:)

于 2011-06-23T00:34:55.927 に答える
1

なぜこのセグメンテーション違反が発生するのか疑問に思っています。

cmdがグローバル変数の場合、その値は書き込みNULL可能ではなく、ローカル変数の場合、その値は不確定であり、使用しないでください(ただし、使用する場合は何でも実行できます。これは、NULLよりも悪いです。多くの場合)。

于 2011-06-22T23:35:25.070 に答える