Visual C++ 2008 で char ポインタを逆参照するときの未処理例外
-
12-09-2019 - |
質問
Visual C++ 2008 で、次のように文字列の文字を変更する古典的な C 開発を実行しようとしています。
void ModifyString(char *input)
{
// Change first character to 'a'
*input = 'a';
}
文字を変更しようとすると、ハンドルされない例外が発生します。Visual Studio 6 または gcc を使用してこれを行うことができるようですが、おそらく何かを忘れているだけかもしれません。Visual Studio は何らかの方法で char* を値で渡しますか (メモリの管理)。もしそうなら、どうすればこれをオフにできますか?
解決
あなたは、おそらくどこかに文字列リテラルを渡しています
ModifyString("oops"); // ERROR!
CおよびC ++あなたが暗黙的にconst char[]
する(タイプchar*
を持っている)文字列リテラルからキャストすることができますが、そのような使用法は廃止されました。あなたがそれらを修正しようとした場合、あなたは(セグメンテーションフォールトやバスエラー別名)アクセス違反を取得しますので、文字列定数は、読み出し専用メモリに割り当てることが可能(と彼らは通常です)されています。コンパイラは、読み出し専用メモリ内の文字列定数を入れていない場合は、プログラムはまだ動作しますが、それは未定義の動作です。
これを行うための正しい方法は、書き込み可能なバッファに文字列をコピーすることです。
// one way:
char mystring[] = "test";
ModifyString(mystring); // ok
// another way:
char mystring[64]; // make sure this is big enough!!
strcpy(mystring, "test");
ModifyString(mystring); // ok
他のヒント
リテラル文字列の入力ですか?それはおそらく問題です。ポインタが何とかメモリ内の読み取り専用の場所を指してしまったようにそうしないとあなたは、より多くのコードを投稿する必要があります。
ModifyString がどのように呼び出されるのかを見ずに、この質問に答えることは不可能です。関数自体は、そのコントラクトに NULL 以外の値が渡されることを前提として正しいものです。
ただし、さまざまなことを行うと、呼び出しサイトが失敗する可能性があります。
- NULLを渡す
- 邪悪なキャストを使用して const char を渡す
私はこれが動作しない理由を正確に言うことはできませんが、問題は、Visual Studio、あなたのコードではありません。何らかの理由で、あなたは、関数に無効なポインタを渡しています。これは、どちらかのNULLポインタである、またはそれはあなたがアクセス権を読んだことがないいくつかのアドレスを指します。
あなたは、コードのいくつかのより多くを投稿する場合は、(どこから呼び出された関数であり、それがどのように呼ばれている?)、私たちは、正確な問題を指摘することができるかもしれません。
それはGCCやVC6で働いていた理由は、それが未定義の動作であることを非常に単純です。 C ++標準では、「これは動作するはずです」、または「これはクラッシュを起こす必要がある」と言っていません。あなたがへのアクセスを持っていないメモリに書き込む場合何が起こるかわかりません。そして、コンパイラ、およびあなたが上でアプリケーションを実行しているシステムに応じて、あなたがアクセスし終わるアドレスが異なります。全くの運によって、あなたはVC2008でコンパイルすると、アクセス違反の原因となったアドレスにヒット。 GCCとVC6の下で、あなたに幸運ではなかったし、 を動作するように登場したコードを持って、単にいくつかのガベージアドレスに書いています。