• ベストアンサー

【C++】同じインスタンスの同じメンバにアクセスしているハズなのに、取得した値が異なる

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

質問者さんのレベル的にありえないとは思うけど、 まさか多重継承してないよね? いや、なければいいんだ。うん。

hogejo
質問者

お礼

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にて行われていること ・同名のファイルを持つ別のプロジェクトが存在すること これらの情報がない限りは、妄想力がないと解決しようのない問題でした。 考えてくださった皆様には申し訳ありませんでした。 多分、プロジェクトをコピーして作ったときに紛れ込んだモノだと思います。 今となっては、「メンバのポインタがずれている」ならば、「クラスの定義が別々なんだろ」と思えますが、そのときは全く気がつきませんでした・・・ ありがとうございました。

hogejo
質問者

補足

多重継承で派生元の2つのクラスに同じ名前のメンバがいる、というケースのこと? その点は調べていませんでした・・・が、そもそも多重継承は使っていないので、この心配は無用なようです。(多重継承は使ったことがないので、少し考え込んでしまいました。) 回答ありがとうございます。 もう少し自分でも考えてみて、解決しなかったら適当に締め切りたいと思います。また何かありましたらよろしくお願い致します。

その他の回答 (2)

回答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にアクセス→大阪市で「大阪市中央区はどこですか?」と質問→「大阪市中央区はここ」が答え

hogejo
質問者

お礼

丁寧にご回答くださりありがとうございました。

hogejo
質問者

補足

大変、申し訳ありません。 私の掲載したソースが間違っていました。 (掲載用に名称等を変えたのですが、間違っていました。) 正 : 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ファイルを一旦全て削除して、ビルドしなおしましたが 結果は同じでした。 私の提供する情報が足りないかもしれませんが、ソースを全部出すわけにも行きませんし、、、

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

とりあえずソースがないことには話が進まないんだけど....

hogejo
質問者

お礼

回答ありがとうございます。 ソースを結構、量があり全部載せるわけにはいきませんので、 問題のメンバ変数へのアクセス部分だけを載せました。(というほどの量でもありませんが。)

関連するQ&A