An integer may be converted to any pointer type. The result is implementation-defined, might not be properly aligned, and might not point to an entity of the referenced type.
だから、「変換するまで」は OK 。 変換した後のポインタをいじくるとどうなるかわからないし、 何が入っているかもわからない、 と理解していました。 may だからコンパイルエラーにしても良いということですか?
The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly freed or reallocated).
ウイルス感染環境作んなボケェ! (スコア:-1, 荒らし)
メモリ破壊コード (スコア:1, 興味深い)
Re:メモリ破壊コード (スコア:2, 参考になる)
別に何を再現する必要も無いのでは?
不定というのは、結果がどうなっても構わないという意味です。
暴走、例外はおろか、鼻から悪魔が飛び出しても言語規約上許されますし、
そんな分かりやすいリアクションではなく、一見正しく動作しているフリをしても構いません。
数多くのプログラマを苦しめてきた、Cの暗黒面の筆頭といって良い仕様です。
Re:メモリ破壊コード (スコア:1, おもしろおかしい)
指定された壊れたメモリ領域を律儀に読み込んでとんでもない動作を実行し続けるだけで。
壊れていようがなんだろうがお構い無しに実行するのがCという言語の仕様。
まあコードからだけでは動作を予測し切る事は一般にできないもんだけど。
Re:メモリ破壊コード (スコア:2, 参考になる)
なんかprintfをつけたら症状が出なくなったからデバッグ完了、と同じ類のvoodoo臭がぷんぷん漂ってきますよ。
Cの規格では確保したバッファの範囲外を読んだり書いたりアドレスを生成するだけで不定になります。
確保したバッファ+1のアドレス生成だけは認められていますが。
Re:メモリ破壊コード (スコア:1, 興味深い)
アドレスを生成した時点で不定だったっけ?
void* pv = (void*)(0xDEADBEEF);
このコードが存在するだけで不定って意味になるけど、pvを使ってアクセスしなければ不定にはならないと思うよ。
Re:メモリ破壊コード (スコア:2, 興味深い)
はポインタの指す先を読み書きしなければ大丈夫です。
整数はどんなポインタにも変換可能と規格で決まっています。
undefined なのは
char buf[1]; や char *buf = malloc ( 1 );
があったときに、(buf-2) や (buf+2) を含む式を評価した場合です。
例えば オーバーフローがあると例外を発生させるような種類の CPU で、
buf がメモリ空間の端っこ付近に割り当てられていたりすると
ひどい目にあうかもしれません。
一方 (buf-1) や (buf+1) は評価できることになってます。
一個までなら配列の範囲外を指すポインタを生成しても
オーバーフローしないと規格で決められています。
先の例で言うと、 buf はメモリ空間の端っこに配置されません。
必ず一要素分以上隙間があります。
Re: (スコア:0)
> buf がメモリ空間の端っこ付近に割り当てられていたりすると
> ひどい目にあうかもしれません。
オーバーフロー検出機構のないCPUで一見正常に実行を続けられるせいで
任意コード実行とかされちゃうほうが「ひどい目」だと思う。
他の高級言語みたいにオーバーフロー検査を言語仕様で強制してほしいくらいなんだが
Re: (スコア:0)
struct buffer { int a,int b, ... } *pBuffer;
pBuffer = new malloc( sizeof(buffer)*MAX_ELEMENT );
pBuffer[-1]やpBuffer[MAX_ELEMENT]を許すには sizeof(buffer) bytes前後に
開けなきゃいけないってなるけど、ランタイムにとってはサイズをもらってるだけの
関係だから「んなもんわかんねーよ」なんじゃないかなー
嘘を書くな嘘を(Re:メモリ破壊コード) (スコア:2)
ポインタが指し示す先のオブジェクトの中には
alignment が問題となるものがある(たとえば、奇数ア
ドレスを持ち得ないなど)ので、整数→ポインタの結果
については実装依存です。
逆もしかり(実装依存)で、特にポインタ→整数で保持
しきれない環境では undefined-behavior です。
余計にアドレスを生成して良いのは配列へのポインタの
場合のみで(対象が malloc では駄目)、配列の最後の
要素を一つだけ越えて生成する場合に限られます(一つ
前は駄目)。
Re:嘘を書くな嘘を(Re:メモリ破壊コード) (スコア:2, 興味深い)
だから、「変換するまで」は OK 。
変換した後のポインタをいじくるとどうなるかわからないし、
何が入っているかもわからない、
と理解していました。
may だからコンパイルエラーにしても良いということですか?
> 余計にアドレスを生成して良いのは配列へのポインタの
> 場合のみで(対象が malloc では駄目)
これは本当ですか?
と、malloc の返すポインタは an array を指せるようになっているのですが、
binary + の項目には malloc で作られた object を指すポインタと
そうでない object を指すポインタを区別する記述は見つかりませんでした。
どこにその記述があるか教えて頂けると助かります。
>(一つ前は駄目)。
ごめんなさい。そうでした。
Re: (スコア:0)
メモリにアクセスする度にソフトウェア的に監査するといった、多大なコストを要求してしまうのです。
現在のPCでは、最低レベルの環境ですら大したコストでは無くなってきましたが、
20年前、30年前の手頃なパソコンやワークステーション、あるいは現在においても組込み分野などでは
とても無視できるものではなく、だからこそそういう無駄あるいは贅沢を排したC言語がもてはやされたのです。
もっともCの規格上そういう機能を持ってはいけないという
Re:嘘を書くな嘘を(Re:メモリ破壊コード) (スコア:1)
int i;
t_hoge a[10], *p=a;
for( i=0; i<10; i++ ){
*(p++) = hoge();
}
みたいなコードを許容するためだ、と書いてあった記憶があります。
この例では計10回 p++ が走りますが、10回目の p++ がエラーになってはいけない、ただそれだけだと。
なので、配列の後ろにアドレス空間上の余白を空けるかどうかとは別問題です。
そもそもポインタが実アドレスや論理アドレス、あるいはそれに準じる値を保持する約束も無いのです。
(もちろん実装するにあたり、常に後方にアドレス空間を空けておくという解決策もありでしょう。)
記事では10回 ++ した p を他の t_hoge* と比較できるかどうかも考察していたと思いますが、
そっちは忘れてしまいました(汗
Re: (スコア:0)
> 開けなきゃいけないってなるけど、
なりません。アドレスを生成することは合法ですが、そこにアクセスした瞬間未定義になります。つまり境界を踏み越えて隣の変数とかmallocの管理領域とかを破壊しても言語仕様上は一向にかまいませんし、実際多数の実装がそうなっています。pBuffer[-1]は別コメントにあるとおりそもそも未定義なので議論を省略。
Re:嘘を書くな嘘を(Re:メモリ破壊コード) (スコア:2)
これはその通りで、実装がどう動くかを理解して書く分
には構わない(実装依存でないのは 0 をポインタに変
換したときだけ、というのを勘違いしてた)。
これも私の嘘でした(何を勘違いしてたんだか…)。
Re: (スコア:0)
> とても無視できるものではなく、
これから言語仕様に追加してほしいという話ですから昔のことは関係ありませんし、組み込みで問題ならフリースタンディング環境は除いてもかまいません。もはやホスト環境では弊害のほうが大きいと思います。
> もっともCの規格上そういう機能を持ってはいけないという決まりもないので、
> そういう安全装置を備えた処理系も探せばあるかもしれません。
というかあります [srad.jp]。
Re:嘘を書くな嘘を(Re:メモリ破壊コード) (スコア:1)
そっちもオッケーだったはず。
t_hoge array[10], *ptr;
for (ptr = array; ptr < array+10; ptr++) {
…
}
みたいなコードでも正しく動くようにってことで、
「array+10」は「ポインタ」としては正しく存在し演算可能。
ただし、大丈夫なのはポインタを扱うところまでで、*(array+10)をやったらアウト。
Re:メモリ破壊コード (スコア:1, 興味深い)
Re:メモリ破壊コード (スコア:1, 興味深い)
言語仕様上は不定として、じゃあ Alchemy はどうしてくれるんだろうって話じゃね?
いけないアソコをおさわりしちゃった時に、Alchemy も何らチェックせず本当にリアルのアソコをおさわりしちゃうのか、それともそこらへんはきっちりチェックして、なんか例外を出すのかと。
あるいは本当におさわりするわけじゃないけども、仮想マシンの中で“世界のアドビ”フラグでも立てて、0xAD0BE の倍数でアホになる挙動をエミュレートするとか。
鼻から悪魔を出してもいいのなら、“じゃあ Alchemy ではこーし(ますっ|ませんっ)”と宣言してくれても何ら違反じゃないよね、っていう。
Re: (スコア:0)
Re:メモリ破壊コード (スコア:2, 参考になる)
コードの中でそれをトラップさせる仕組みを追加しても構いません。
ある意味盲点ですが「そのまま正しく動作」させても規格上は問題ありません。
MS-DOS の頃など、V-RAM や OS のワークエリア等を直に読み書きしていたのがこれにあたります。
処理系を実装するにあたって何も定められていない以上、
そのようなコードを放置して、あるがままに動作させても言語仕様には違反しませんし、
処理系としてそのような動作を保証しても構いません。
でもそれは特定の処理系における実装の例に過ぎず、
他の環境でどうなるかは分からないし、環境ごとに異なる結果となっても、
そのいずれもがCの仕様に準じた正しい処理系だと言えるということです。
Re:メモリ破壊コード (スコア:1, すばらしい洞察)
そろそろ知ったかぶりが痛々しい
Re:メモリ破壊コード (スコア:1, おもしろおかしい)
元コメには、初級C言語を学んで欲しい。
http://www.st.rim.or.jp/~phinloda/cqa/cqa7.html [rim.or.jp]
Re:メモリ破壊コード (スコア:1)
C だけじゃなく C++ も可能と言ってるのだから、throw や try/catch くらい視野に入っているでしょう。