Board index » cppbuilder » C++ bug? Strange mis-reading of member variable

C++ bug? Strange mis-reading of member variable


2006-11-10 09:09:57 PM
cppbuilder91
Hi there,
I would like to ask if this issue is somehow known:
I have a global function in the cpp unit of the main TForm ("FormMain"),
which can be called from deeper inside the program (non-gui parts) to
bring up a Windows requester and return the answer. However, from this
function I somehow cannot access members of FormMain - right at the
beginning of the function there is a line "TEdit *ted = FormMain->Edit1;",
but after executing it in the de{*word*81}, you can Watch or Inspect the right
hand side to see that it indeed points to a TEdit as it should, but on the
left hand side the variable ted contains just some garbage!
Indeed in the CPU view, you can see that there is one surplus indirection:
mov edx, [0x00517564] ->now edx == FormMain, a pointer to the form
mov ecx, [edx] ->strange indirection!
mov eax, [ecx+0x000002c4] ->if this was [edx+0x2c4] it would be fine!
mov [ebp-0x84], eax ->save the result
I have made a small test program with a similar setup (global function in
the same unit as main form, accessing member variable), but there
everything is fine, and in the CPU view there is no superfluous
indirection as above.
Man, this is a little scary - has someone dealt with this before??? Oh by
the way, this happens in Builder 4, but also if I replace the bcc32 by
version 5.5.1 from the free commandline tools.
Best regards,
Soenke
 
 

Re:C++ bug? Strange mis-reading of member variable

Soenke Senff wrote:
Quote
.. However, from this
function I somehow cannot access members of FormMain
Is only the de{*word*81} telling you that?
What happens if you run your program outside the IDE?
Quote
I have made a small test program with a similar setup (global function
in the same unit as main form, accessing member variable), but there
everything is fine, and in the CPU view there is no superfluous
indirection as above.
Add more code until it comes again.
Hans.
 

Re:C++ bug? Strange mis-reading of member variable

On Fri, 10 Nov 2006, Hans Galema wrote:
Quote
Soenke Senff wrote:
>.. However, from this function I somehow cannot access members of FormMain

Is only the de{*word*81} telling you that?

What happens if you run your program outside the IDE?
When I access the pointed-to object after (unsuccessfully) reading the
pointer from FormMain, i.e. "ted->Visible = true", I get an AV. That's
without the de{*word*81}, even without debugging information in the code.
Quote
>I have made a small test program with a similar setup (global
function in
>the same unit as main form, accessing member variable), but there
>everything is fine, and in the CPU view there is no superfluous indirection
>as above.

Add more code until it comes again.
Right now I am trying the opposite, stripping the non-working code of as
much as possible. I've already eliminated all the other forms, and the
error is still there. I'll let you know what I find.
Regards,
Soenke
 

{smallsort}

Re:C++ bug? Strange mis-reading of member variable

Soenke Senff wrote:
Quote
mov edx, [0x00517564] ->now edx == FormMain, a pointer to the form
mov ecx, [edx] ->strange indirection!
Now ECX points to the VMT.
Quote
mov eax, [ecx+0x000002c4] ->if this was [edx+0x2c4] it would be fine!
EAX contains a pointer to the method with VMT-Index 0xb1 (== 0x2c4>>2).
Very strange.
--
Regards,
Andreas Hausladen
 

Re:C++ bug? Strange mis-reading of member variable

Hi,
maybe this is related to a bug (?) a colleague of mine recently stumbled into.
--- snip ---
#include <vcl.h>
#pragma hdrstop
// self
#include "formMain.h"
void test1(void)
{
TForm1* f = Form1;
f->Caption = "Test1";
}
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
void test2(void)
{
TForm1* f = Form1;
f->Caption = "Test2";
}
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
test2();
test1();
}
--- snap ---
'test2()' runs fine, 'test1' crashes. The only difference seems to be, that
'test1()' is defined before the definition of the global pointer 'Form1', but as
far as I know that shouldn't make any difference, correct? 'Form1' is declared
as "extern PACKAGE TForm1 *Form1;" in the header.
The code in test2 looks like this:
formMain.cpp.19: TForm1* f = Form1;
00401A78 8B15B8354000 mov edx,[$004035b8]
00401A7E 8955D4 mov [ebp-$2c],edx
The code in test1 looks like this (!):
formMain.cpp.9: TForm1* f = Form1;
00401A1C 8B15B8354000 mov edx,[$004035b8]
00401A22 8B0A mov ecx,[edx] <<<<<< Oops!
00401A24 894DD4 mov [ebp-$2c],ecx
Regards
Eike Petersen
Soenke Senff wrote:
Quote
Hi there,

I would like to ask if this issue is somehow known:

I have a global function in the cpp unit of the main TForm ("FormMain"),
which can be called from deeper inside the program (non-gui parts) to
bring up a Windows requester and return the answer. However, from this
function I somehow cannot access members of FormMain - right at the
beginning of the function there is a line "TEdit *ted =
FormMain->Edit1;", but after executing it in the de{*word*81}, you can Watch
or Inspect the right hand side to see that it indeed points to a TEdit
as it should, but on the left hand side the variable ted contains just
some garbage!

Indeed in the CPU view, you can see that there is one surplus indirection:

mov edx, [0x00517564] ->now edx == FormMain, a pointer to the form
mov ecx, [edx] ->strange indirection!
mov eax, [ecx+0x000002c4] ->if this was [edx+0x2c4] it would be fine!
mov [ebp-0x84], eax ->save the result

I have made a small test program with a similar setup (global function
in the same unit as main form, accessing member variable), but there
everything is fine, and in the CPU view there is no superfluous
indirection as above.

Man, this is a little scary - has someone dealt with this before??? Oh
by the way, this happens in Builder 4, but also if I replace the bcc32
by version 5.5.1 from the free commandline tools.

Best regards,
Soenke
 

Re:C++ bug? Strange mis-reading of member variable

On Sun, 12 Nov 2006, Eike Petersen wrote:
Quote
maybe this is related to a bug (?) a colleague of mine recently stumbled
into.
[...]
'test2()' runs fine, 'test1' crashes. The only difference seems to be, that
'test1()' is defined before the definition of the global pointer 'Form1', but
as far as I know that shouldn't make any difference, correct? 'Form1' is
declared as "extern PACKAGE TForm1 *Form1;" in the header.

The code in test2 looks like this:

formMain.cpp.19: TForm1* f = Form1;
00401A78 8B15B8354000 mov edx,[$004035b8]
00401A7E 8955D4 mov [ebp-$2c],edx

The code in test1 looks like this (!):
formMain.cpp.9: TForm1* f = Form1;
00401A1C 8B15B8354000 mov edx,[$004035b8]
00401A22 8B0A mov ecx,[edx] <<<<<< Oops!
00401A24 894DD4 mov [ebp-$2c],ecx
Thanks, that solved it for me too! The routine was in fact placed before
the actual pointer declaration itself ("TFormMain *FormMain"), and now
I've moved it.
The problem seems to be that a pointer with an "extern PACKAGE"
declaration is retrieved from a table, while a normal pointer defined
inside the unit is retrieved directly from some location. When I used the
pointer before its re-declaration as "TFormMain *FormMain", the compiler
got these two things mixed up. I guess in one way or another this would
qualify as a bug..
Best regards,
Soenke
 

Re:C++ bug? Strange mis-reading of member variable

In article
< XXXX@XXXXX.COM >,
Soenke Senff < XXXX@XXXXX.COM >wrote:
Quote
The problem seems to be that a pointer with an "extern PACKAGE"
declaration is retrieved from a table, while a normal pointer defined
inside the unit is retrieved directly from some location. When I used the
pointer before its re-declaration as "TFormMain *FormMain", the compiler
got these two things mixed up. I guess in one way or another this would
qualify as a bug..
I'd love to see a simple test case added to QC so that this bug can
be squashed.
--
-David
Quis custodiet custodes ipsos?
 

Re:C++ bug? Strange mis-reading of member variable

David Dean wrote:
Quote
I'd love to see a simple test case added to QC so that this bug can
be squashed.
It seems to me that this bug is already in QC. At least I know for a
long time that it's bad idea to place a user code in cpp before
autocreated lines (#pragma package, #pragma resource, TForm1 *Form1 and
so on) ...
Alex.
 

Re:C++ bug? Strange mis-reading of member variable

In article < XXXX@XXXXX.COM >, AlexB < XXXX@XXXXX.COM >
wrote:
Quote
It seems to me that this bug is already in QC. At least I know for a
long time that it's bad idea to place a user code in cpp before
autocreated lines (#pragma package, #pragma resource, TForm1 *Form1 and
so on) ...
Where? I did look, but maybe you know a better search term.
--
-David
Quis custodiet custodes ipsos?
 

Re:C++ bug? Strange mis-reading of member variable

David Dean wrote:
Quote
In article < XXXX@XXXXX.COM >, AlexB < XXXX@XXXXX.COM >
wrote:

>It seems to me that this bug is already in QC. At least I know for a
>long time that it's bad idea to place a user code in cpp before
>autocreated lines (#pragma package, #pragma resource, TForm1 *Form1 and
>so on) ...

Where? I did look, but maybe you know a better search term.

I reported this as 36546.
Regards
Eike
 

Re:C++ bug? Strange mis-reading of member variable

In article <4559b0d2$ XXXX@XXXXX.COM >,
Eike Petersen < XXXX@XXXXX.COM >wrote:
Quote
I reported this as 36546.
Thank you. I'll try to get to it this week.
--
-David
Quis custodiet custodes ipsos?