2011-01-15 8 views
0

可能性の重複:
Modifying C string constants?char * arr [5]のアクセス違反= {...}、これは何ですか?

私が言及した行にアクセス違反を取得なぜあなたは説明できますか?私はそれが私のプロセスメモリだと私はアクセスし、それの内容を変更することができますね。

#include <stdio.h> 

int main() 
{ 
    char* list[5]={"An","exam","on","Hall oween","night!!!!"}; 
    char **p; 
    p=list; 
    *(*(p+1)+2)='A'; // <==== Access vioalation here 
    return 0; 
} 
+1

配列にインデックスを付けるために[]表記が嫌いですか? – CodesInChaos

+0

いいえ、私の学生はちょうど尋ねた。 –

+0

@CodeInChaos - 実際のプログラマーは 'goto'を使ってループを書く。 :P –

答えて

5

コードは、第2列に第三の文字を設定したいすなわちp[1][2]='A';と等価です。

しかし、文字列は文字列リテラルなので不変であり、内容を変更しようとすると未定義の動作が発生します。特に、それらは読み取り専用メモリに配置することができます。その場合、アクセス違反が発生します。

通常、実行可能ファイルは、コード、グローバル変数、および定数のための異なるセクションで構成されています。実行ファイルはプロセスにマップされ、メモリアクセス特権は実行可能ファイルで宣言されたものに設定されます。通常、コードはReadExecuteに、グローバル変数はReadWriteに、定数はReadに設定されます。
次に、CPUはこれらのメモリアクセス設定(64ビットCPUでのみ実行)を実行します。 VirtualProtectを使用して、手動でメモリの保護を変更することができます。ページの細分性のみがあることに注意してください。

+0

これが文字列定数の場合は、constキーワードではこれはなぜ真ではありませんか? –

+0

それはどういう意味ですか? AFAIKのほとんどのコンパイラは、*コンパイル時の定数を(constにキャストした変数ではなく)読み込み専用メモリに入れます。しかし、彼らは彼らに標準的な手紙によれば、未定義の行動であるため、読んでいないように自由ではありません。 – CodesInChaos

+1

@Green Code - なぜ、文字列リテラルが 'const char []'の代わりに 'char []'ではないのかというと、その理由は、標準が書かれたときの既存のCコードとの下位互換性のためです。 'const'はコンパイラによって普遍的に実装されていなかったので、既存のコードは' char * c = "this"; 'を使用しなければなりませんでした。標準では、文字列リテラルを変更することは悪い考えであると判断しましたが、プリスタンダードコンパイラ用に設計されたコードが壊れないようにしていました。それ以来、私たちは苦しんできました。 :P –

3

文字列定数を変更しようとしていますが、これは未定義の動作です。この場合、コンパイラはそれらを読み込み専用データセグメントに入れます。

+0

コンパイラはどうしますか?たとえば、自分のプロセスに属するメモリのモードを読み取り専用に変更したい場合は、どうしたらいいですか? –

+0

Windows上で 'VirtualProtect'を使うことができます。 – CodesInChaos

2

Cの文字列リテラルは変更不可です。文字列リテラルへのポインタの配列を宣言してから、それを変更しようとしています。

関連する問題