以下のコードはメモリ破壊につながるでしょうか?
WindowsVista+VC9.0で実行しました。
#include <stdio.h>
class A
{
public:
void test(){ printf("test\n"); }
int i;
};
int main(void)
{
A* a; // 実体をnewしない
a->test(); // newしないでメソッドにアクセス。
// アプリは落ちずにちゃんと画面にtestと出る。
//a->i = 3; // ←これはアプリが落ちる。
return 0;
}
a->i = 3をしてしまうと、確保していない領域に
書き込んでしまい落ちるのは理解できます。
ですが、a->test()は問題にはならないのでしょうか?
落ちないということはメモリを破壊していないということなのでしょうか?
メモリを書きかえるような要素が見られないので
してないのではないでしょうか。
コードそのものの意義に疑問が残りますが。
そださんへ
ありがとうございます。
ということは上記記述で即席staticメソッドが作れるということでしょうか。
class A {
static void test(){}
};
A::test();
と同じようなことが、
class A {
void test(){}
};
A* a;
a->test();
でもできるということでしょうか?
何が訊きたいのか良くわかんないんだけど
A* a; // uninitialized
a->test(); // function call via uninitialized pointer
は「原則、動かない」わけだ
virtual void test() { ... } にすれば100%動かないから試して味噌。
「たまたま偶然、特定状況下では動くことも有るかもしれない」(=バグっているコードがたまたま動く) のと
「どんなコンパイラでコンパイルしても、どんなOSで実行しても、動く」(=正しいコードが正しく実行される) のと
では大きく違う
提示例がうまく動くとは言語規格書もコンパイラのマニュアルも保証してくれないわけで
動作保証をばーとん氏が自分で行うのなら勝手にすればいい。
static な void A::sfunc() を A::sfunc(); と呼ぶのは動作保証があるし
a->sfunc(); と呼んでも a の値は使用されないので動作保証があるよ
tetrapodさんへ
ありがとうございます。
意味不明な質問をしてしまいすみませんでした。
試してみるとvirtualをつけると落ちました。
それとstaticメソッドを
クラス名::メソッド名()形式だけでなく
クラス型の変数->メソッド名の形式で呼べるのですね。
知りませんでした。
uninitialized/NULL なポインタで virtual が呼べないのは当然なんだけど
non-virtual なら [コンパイラの実装上、呼べない理由が無い] ので
「呼び出すだけ」なら呼べるだろうね
A* a; があるとき a->non_virtual_memfunc(arg1, arg2); を、コンパイラは
non_virtual_mem_func_of_class_A(a, arg1, arg2); のように翻訳するんで。
non_virtual_memfunc() の中でメンバー変数に触ったりすると即死だけど。
# メンバー変数に一切触らないのであれば static メンバー関数にすればいい
# こっちなら言語規格書上の動作保証があるわけで
NULL なポインタに対して non-virtual な呼び出しを行う例だったら MFC にあったりするんだな
CWnd::GetSafeHwnd() なんかがそう
言語規格書が保証してないところを Microsoft が保証している例だったりする
# uninitialized なポインタに対して CWnd::GetSafeHwnd() を呼ぶと死ぬけどさ
このメモリー破壊に関して、
C++言語と言うより、機械語ではどうなるかが重要になるかとおもいます。
機械語レベルでは、大まかに分けると「ソースコード領域とデータ領域」とに分かれます。
C++では、classの中に関数を挿入することが出来、動的に関数を
複製出来るように見えますが、機械語に変換の都合で、
「ソースコード領域とデータ領域」に分解されます。
そもそも、関数が動的に作成されるのは非効率のため、
通常は、関数はプログラム上では1つだけとなり、それに渡されるデータ
領域だけが複製が作成されます。
そのため、NULLを渡した場合、その変数にアクセスしなければ、
問題がないと思われます。
virtual定義だと、関数の場所を保存する変数のような扱いとなり、
メモリアクセスしているためエラーが出ていると思われます。
とりあえず最初のコードは間違ったコードだということだけは認識しといてくれよ
動けば正しいわけじゃないんだよ
鼻から悪魔が出てくる代わりに
投稿したら色々突かれる言うことか…
難しすぎてよく分からん。
それを知っていないと何か問題があるのか?の方に
興味があります。
3か月も前の質問だし質問者の返信もとまっているから
もういいような気がするけど・・・
ツイート | ![]() |