.rodata
であることは確信していますか?このコード
const int temp = 10;
int main(void) {
int *ptr = &temp;
*ptr = 100;
}
LinuxではGCC 5.2.1がクラッシュします。 nm
は、temp
が.rodata
に存在することを示します。しかし
、変数は自動記憶域期間を持っており、それが.rodata
セクションの読み取り専用ページに存在する代わりに、そのスタック上に配置されているので
int main() {
const int temp = 10;
int *ptr = &temp;
*ptr = 100;
}
が、クラッシュしません。
またC11ドラフトn1570、6.7.3項6:
試みは非const
と左辺値を使用してconst
-qualifiedタイプで定義されたオブジェクトを変更するためになされた場合 - 修飾タイプの場合、の動作は未定義です。 [...]
そしてもちろん、未定義の動作は次のことを意味します
行動を、移植性や誤ったプログラム構築物の使用時や、この国際規格は何の要件を課していないそのため、誤ったデータの
実際に何かが起こる可能性があり、プログラムがこれでクラッシュしなくても、それは間違いです。いずれの場合においても
、あなたは警告を得ました。 Cコンパイラが警告を発するときはいつでも、実際にはプログラマとしてエラーを受け取ります(具体的には-Werror
を設定しても)。実際にはエラーであるこれらのことを真のエラーにすることはできないという、ある種の悪い振る舞いに依存する古いコードがたくさんあるだけです。それは完璧であるような有効なC、とだけあなたは未定義の動作が発生し、このptr
経由temp
を変更しようとするたびに - C標準はint *ptr = &temp;
が間違っていることを言っていないことを
は
注意。
'int * ptr = &temp;'は制約違反です。コンパイラが文句を言っていない場合、コンパイラを正しく呼び出す方法を見つけ出す –
これは、メモリを扱う際にC/C++で得られる柔軟性のためです。あなたが何をしているのかが分かっていれば、この柔軟性は他の人にはセグメンテーション違反が予想されます。しかし、コンパイラは、そのような柔軟性を警告/警告する良い仕事をしています。 – sameerkn