C++Builder6.0を使った画面アプリです。1つのexeとしてビルドしています。
メンバ変数へのアクセス
firstFormインスタンスのメンバ stNode.count を 次の2箇所からアクセスしています。
(正確にはfirstFormが持つ、stNode構造体メンバのcountにアクセス)
(1)firstFormのメンバ関数から読み取る
(2)firstFormから呼び出されるsecondFormのメンバ関数から読み取る
なぜか(1)と(2)で読み取った値が異なります。
しかし値が変わるような処理はしていません。
firstForm, secondForm はそれぞれ、TFromから派生したクラスです。
--------------------------------------------------------------------
1回目のアクセス。期待する値を取得できた。
this ( TForm から派生する firstFormのインスタンスのメンバ関数からのアクセス )の値
:01682E0C
nnum = this->stNode.count;
004037C1 8B4508 mov eax,[ebp+0x08] //多分、thisポインタをeaxに格納
004037C4 8B90DC030000 mov edx,[eax+0x000003dc] //thisポインタのメンバである stNode.nodesuの中身をedxに格納
004037CA 899578FFFFFF mov [ebp-0x00000088],edx //edxの中身をローカル変数nnumに格納
EAX 01682E0C
EDX 0000022D
EBP 0012F8F0
--------------------------------------------------------------------
2回目のアクセス。( TForm から派生する secondFormのインスタンスのメンバ関数からのアクセス )
secondForm のポインタはthisと同じである
:01682E0C
nnum = secondForm->stNode.count;
004072B7 8B0D409B4900 mov ecx,[__ectbl__ __LateVCLInit + 0x2C]
004072BD 8B01 mov eax,[ecx]
004072BF 8B90D0030000 mov edx,[eax+0x000003d0]
004072C5 895580 mov [ebp-0x80],edx
ECX 0049A5EC
EAX 01682E0C
EDX 0177F280
----------------------------------------------------------------------
どちらの場合もEAXにfirstFormへのポインタが格納されているようです。
なのに、メンバへのオフセット?が 1回目は 0x03dc , 2回目は 0x03d0 となり12バイトずれて
います。(オフセットがやたら大きい気はします。)
メモリの中身をデバッガで確認すると、確かに12バイトずれたところに欲しい値があります。
ソースコードを眺めてもさっぱりわかりません。
何を調べれば良いのかさっぱり分かりません。
解決できる気がしないのですが、いろいろ考えるのも勉強になると思うので
「こういう可能性もあるのでは?」「これを調べたら?」といったアドバイスなど頂けたら助かります。
#不可解な事象というのは往々にして、全然関係ない初歩的なことに原因があるものですが・・・今回もそうなんだろうか。
No.3ベストアンサー
- 回答日時:
質問者さんのレベル的にありえないとは思うけど、
まさか多重継承してないよね?
いや、なければいいんだ。うん。
この回答への補足
多重継承で派生元の2つのクラスに同じ名前のメンバがいる、というケースのこと?
その点は調べていませんでした・・・が、そもそも多重継承は使っていないので、この心配は無用なようです。(多重継承は使ったことがないので、少し考え込んでしまいました。)
回答ありがとうございます。
もう少し自分でも考えてみて、解決しなかったら適当に締め切りたいと思います。また何かありましたらよろしくお願い致します。
firstFormとsecondFormで、firstFormの各メンバのアドレスを比較してみたところ
所々、微妙に違っていました。
よくよく確認したところ、
secondFormがincludeしているfirstForm.hと
firstFormがincludeしているfirstForm.hが別モノでした。
(A)では(X)ををincludeしているつもりでしたが
(Y)をincludeしていました。
※includeファイルの検索パスはプロジェクトで共通のはずなので
同じヘッダファイル名ならば同じ実ファイルを指すと思っていましたが
単純にそうとは言えないようでした。
C++BuilderのIDE画面で#includeの位置にリンクするファイルを開くと、
・MyProject/firstFormではMyProject/firstForm.h が開く
・MyProject/secondFormではAnotherProject/firstForm.h 開く
上記のようになっていました。プリプロセスの結果も、それを反映したものになっています。
MyProject
+--+(X) firstForm.h
+firstForm.cpp( #include <MyProject の firstForm.h> )
+secondForm.h
+(A) seconfForm.cpp ( #include <AnotherProject の firstForm.h> )
AnotherProject
+--+(Y) firstForm.h
+firstForm.cpp
+secondForm.h
+seconfForm.cpp
・firstFormとsecondFormが別々のモジュールになっていること
・firstFormの構造の宣言が.hにて行われていること
・同名のファイルを持つ別のプロジェクトが存在すること
これらの情報がない限りは、妄想力がないと解決しようのない問題でした。
考えてくださった皆様には申し訳ありませんでした。
多分、プロジェクトをコピーして作ったときに紛れ込んだモノだと思います。
今となっては、「メンバのポインタがずれている」ならば、「クラスの定義が別々なんだろ」と思えますが、そのときは全く気がつきませんでした・・・
ありがとうございました。
No.2
- 回答日時:
「thisポインタは、現在実行しているメンバ関数の、オブジェクトを示す」のは理解していますか?
これは「firstFormのメンバ関数に突入した瞬間にthisはfirstFormを指し、secondFormのメンバ関数に突入した瞬間にthisはsecondFormを指す」と言う事。
これは「今、自分はどこにいますか?」って聞いているようなもので、東京都に居れば答えは「東京都」になり、大阪市に居れば答えは「大阪市」になるのと同じ。
従って、1回目のアクセスの
nnum = this->stNode.count;
は
nnum = firstForm->stNode.count;
と同等。
これは、東京都に来て「中央区はどこですか?」と聞いているようなもので、この質問の答えは「東京都の中央区はここです」になる。そして「東京都中央区はどこですか?」と聞いているのと同等。
「firstForm->stNode.count」と「secondForm->stNode.count」は「実体が異なる、別々の変数」なのは自明。異なるオブジェクトの中身を見てるんだから、当たり前といえば当たり前。
同じ「中央区」でも「東京都中央区」と「大阪市中央区」は違う場所です。
従って
nnum = firstForm->stNode.count; //東京都で「東京都中央区はどこですか?」と質問
nnum = secondForm->stNode.count; //大阪市で「大阪市中央区はどこですか?」と質問
が「異なる値になる」のと同様に
nnum = this->stNode.count; //東京都で「中央区はどこですか?」と質問
nnum = secondForm->stNode.count; //大阪市で「大阪市中央区はどこですか?」と質問
が「異なる値になる」のは当然。
質問者さんがやりたい事は、多分、
1回目のアクセス(firstFormのメンバ関数からのアクセス)
nnum = this->stNode.count; //東京都で「中央区はどこですか?」と質問
2回目のアクセス(secondFormのメンバ関数からのアクセス)
nnum = firstForm->stNode.count; //大阪市で「東京都中央区はどこですか?」と質問
なのではなかろうか?
firstFormのメンバ関数の中でthis->stNode.countにアクセス→東京都で「中央区はどこですか?」と質問→「東京都中央区はここ」が答え
secondFormのメンバ関数の中でthis->stNode.countにアクセス→大阪市で「中央区はどこですか?」と質問→「大阪市中央区はここ」が答え
firstFormのメンバ関数の中でfirstForm->stNode.countにアクセス→東京都で「東京都中央区はどこですか?」と質問→「東京都中央区はここ」が答え
secondFormのメンバ関数の中でfirstForm->stNode.countにアクセス→大阪市で「東京都中央区はどこですか?」と質問→「東京都中央区はここ」が答え
firstFormのメンバ関数の中でsecondForm->stNode.countにアクセス→東京都で「大阪市中央区はどこですか?」と質問→「大阪市中央区はここ」が答え
secondFormのメンバ関数の中でsecondForm->stNode.countにアクセス→大阪市で「大阪市中央区はどこですか?」と質問→「大阪市中央区はここ」が答え
この回答への補足
大変、申し訳ありません。
私の掲載したソースが間違っていました。
(掲載用に名称等を変えたのですが、間違っていました。)
正 :
2回目のアクセス
nnum = firstForm->stNode.count;
>1回目のアクセス(firstFormのメンバ関数からのアクセス)
>nnum = this->stNode.count; //東京都で「中央区はどこですか?」と質>問
>2回目のアクセス(secondFormのメンバ関数からのアクセス)
>nnum = firstForm->stNode.count; //大阪市で「東京都中央区はどこですか?」と質問
>
>なのではなかろうか?
おっしゃるとおり、そう意図しています。私の掲載時のミスで話がややこしくなりましたが、実際に問題がおきているソースでは
secondFormのメンバ関数から
firstFormのstNodeにアクセスしています。
-------------------------------
改めてポインタについて説明致します。
firstFormでのthisの値
:01682E0C
secondFormで確認した、firstForm のポインタは(firstFormの)thisと同じである
:01682E0C
両者が同じ値であることから、同じオブジェクトを指していると思います。
アクセス時のオフセットが異なるところが不思議だと思っています。
1回目は 0x03dc , 2回目は 0x03d0
(もし2回目も0x03dcになっていれば、欲しい値にアクセスできるのですが・・・。)
------------------------------
objファイルを一旦全て削除して、ビルドしなおしましたが
結果は同じでした。
私の提供する情報が足りないかもしれませんが、ソースを全部出すわけにも行きませんし、、、
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# Cのオブジェクトファイルの逆アセンブル 5 2023/05/13 01:51
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
- JavaScript オブジェクト配列の各メンバを任意の式で評価して、その評価値が最大のオブジェクトを返す関数はありますか 2 2023/05/20 15:02
- C言語・C++・C# C言語 2 2022/07/21 00:02
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- その他(プログラミング・Web制作) このプログラミングをどう組みますか? Googlecolabでやってるんですが、出来る方お願いします 1 2022/07/13 10:52
- 法学 不正アクセス禁止法の扱いについて 4 2022/03/23 18:13
- その他(プログラミング・Web制作) どういうプログラムで組みますか?google colabでやってるんですけど、出来る方お願いします。 1 2022/07/17 18:41
- PHP php 確認表示画面で値をSESSIONから取り出す理由の解釈は正しいでしょうか? 1 2023/06/09 17:39
- 会社・職場 一人のメンバだけに土日出勤がある面倒な作業を丸投げ、一方で、上司とそれ以外の同僚達はそのメンバだけハ 4 2023/07/21 10:31
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
セグメントエラー
-
戻り値で構造体を返すことは可...
-
init関数の意味
-
C言語でのconstを返す関数
-
fopne で失敗する原因
-
C言語の関数と配列に関する質問
-
コンストラクタでnewを失敗した...
-
Run-Time Check Failure #3とい...
-
ハンドル、アドレス、ポインタ...
-
C言語のポインタに直接アドレス...
-
LPSTR型の初期化について
-
VBはCを混乱させる?
-
ハンドルはポインタか
-
構造体の中の構造体
-
パスからファイル名を抽出
-
C言語でポインタを使ってピタ...
-
単方向リスト
-
AESのC言語による実装
-
ExcelVBAでのkernel32(64bit)
-
nullポインタを逆参照とは?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
C言語の関数と配列に関する質問
-
戻り値で構造体を返すことは可...
-
fopne で失敗する原因
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
LPSTR型の初期化について
-
セグメントエラー
-
アプリを32bitから64bit移行
-
コンストラクタでnewを失敗した...
-
ExcelVBAでのkernel32(64bit)
-
Cで作成したDLL関数をVBから呼...
-
ハンドルはポインタか
-
DLL<->VB間での受け渡し(文字...
-
C言語でのconstを返す関数
-
ポインタについて
-
参照型で受け取った引数をポイ...
-
TCHAR文字列内の検索について
-
デバイスハンドルとは?
-
基本アルゴリズムの『返す』の...
おすすめ情報