Board index » cppbuilder » Anybody can reproduce this BCB2006 error?

Anybody can reproduce this BCB2006 error?


2007-10-16 07:50:11 PM
cppbuilder97
I came across this error while I was updating my older BCB6
application to BCB2006. Before posting it to Quality Central
I just wanted to check if the problem is not in my code. I was
able to reduce the problem to a quite simple code.
I can reproduce the error with the following steps:
Start BCB2006, create a VCL Forms Application. Leave the form
empty and paste the following code to the file Unit1.cpp:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <string>
#include <fstream>
#include <io.h>
#include <locale>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
using namespace std;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
// use implementation defined locale
setlocale( LC_ALL, "" ); // C functions
locale::global(locale("")); // C++ STL
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
std::ofstream ofs("temp.txt");
std::string s("tempstring");
ofs << s;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
//
}
//---------------------------------------------------------------------------
Go to the project options and set:
Linker/Linking/Use dynamic RTL Off
Linker/Linking/Full debug info [-b] On
Build the application and run it.
Close the form - ends up with 'access violation .... write of address....'
The error will disappear if all the code from TForm1's
destructor is moved to TForm1::FormClose() event or if
Dynamic RTL is used.
Using CodeGuard gives this information:
Error 00064. 0x100C30 (Thread 0x0634):
Method called on freed object: Attempt to access 8 byte(s) at 0x0105A8C0.
| c:\program files\borland\bds\4.0\include\dinkumware\xlocale line 104:
| }
|
|>void _Incref()
| { // safely increment the reference count
| _Lockit _Lock(_LOCK_LOCALE);
Call Tree:
0x004057EC(=project1.exe:0x01:0047EC) c:\program files\borland\bds\4.0\include\dinkumware\xlocale#104
0x0041A948(=project1.exe:0x01:019948)
0x0040CBCA(=project1.exe:0x01:00BBCA)
0x00404126(=project1.exe:0x01:003126) c:\program files\borland\bds\4.0\include\dinkumware\ios#125
0x00402FA9(=project1.exe:0x01:001FA9) c:\program files\borland\bds\4.0\include\dinkumware\ostream#51
0x004023DE(=project1.exe:0x01:0013DE) c:\program files\borland\bds\4.0\include\dinkumware\fstream#770
Any help appreciated.
Vaclav
 
 

Re:Anybody can reproduce this BCB2006 error?

"Vaclav Cechura" < XXXX@XXXXX.COM >wrote:
Quote
Linker/Linking/Full debug info [-b] On
[-b] is a typo. should be:
Linker/Linking/Full debug info [-v] On
 

Re:Anybody can reproduce this BCB2006 error?

1) Yes I can produce a problem with your code - not sure the failure is
exactly the same.
Here's my stack without codeguard:
:00404726 ; std::locale::id::id
:00402FFB std::basic_filebuf<char, std::char_traits<char>
Quote
::_Initcvt(this=:0012FE80, _Newpcvt=:00BF3AF0)
:00402742 std::basic_filebuf<char, std::char_traits<char>
Quote
::open(this=:0012FE80, _Filename=:004531B0, _Mode=2, _Prot=438)
:00401FDE std::basic_ofstream<char, std::char_traits<char>
Quote
::basic_ofstream<char, std::char_traits<char>>(this=:0012FE78,
_Filename=:004531B0, _Mode=2, _Prot=438)
:00401E88 TForm1::~TForm1(this=:00B91CB0)
:51f5f45a rtl100.@Classes@TComponent@DestroyComponents$qqrv + 0x4a
:0044E05A _init_exit_proc(init_table=:0045F6B8, is_exit=1)
:0044E0A1 _cleanup()
:0044D311 __exit(quick=0, dontexit=0, errcode=0)
:0044D365 exit(c=0)
:0044E26A _startup(mod_table=:00453034)
The stack with Codeguard:
:00405730 std::locale::facet::_Incref(this=:0100A8C0)
:0041A760 std::locale::locale(this=:00FD0960)
:0040CB41 std::ios_base::_Init(this=:0012FEC8)
:0040406A std::basic_ios<char, std::char_traits<char>
Quote
::init(this=:0012FEC8, _Strbuf=:0012FE70, _Isstd=false)
:00402EED std::basic_ostream<char, std::char_traits<char>
Quote
::basic_ostream<char, std::char_traits<char>>(this=:0012FE68,
_Strbuf=:0012FE70, _Isstd=false)
:004023DE std::basic_ofstream<char, std::char_traits<char>
Quote
::basic_ofstream<char, std::char_traits<char>>(this=:0012FE68,
_Filename=:004591D1, _Mode=2, _Prot=438)
:0040225D TForm1::~TForm1(this=:00FA1CB0)
:51f5f45a rtl100.@Classes@TComponent@DestroyComponents$qqrv + 0x4a
:00453E02 _init_exit_proc(init_table=:004659A8, is_exit=1)
:00453E49 _cleanup()
:004530B9 __exit(quick=0, dontexit=0, errcode=0)
:0045310D exit(c=0)
:00454012 _startup(mod_table=:00459034)
Part of the codeguard report:
Method called on freed object in process: locale_vaclav_cechura.exe(2868) -
c:\program files\borland\bds\4.0\include\dinkumware\xlocale#102
Attempt to access 8 byte(s) at 0x0100A8C0.
0x00405730 - c:\program
files\borland\bds\4.0\include\dinkumware\xlocale#102
0x0041A760 - locale0.cpp#121
0x0040CB41 - ios.cpp#136
0x0040406A - c:\program files\borland\bds\4.0\include\dinkumware\ios#125
0x00402EED - c:\program
files\borland\bds\4.0\include\dinkumware\ostream#51
0x004023DE - c:\program
files\borland\bds\4.0\include\dinkumware\fstream#765
The object (0x0100A8C0) [size: 64 bytes] was created with new
0x0040DC5E - locale.cpp#43
0x00401F41 - C:\dev\bcbtests\localecausedcrash\Unit1.cpp#25
0x5207946C
0x00401971 -
C:\dev\bcbtests\localecausedcrash\locale_vaclav_cechura.cpp#39
0x00454009 - startup.c#249
The object (0x0100A8C0) was deleted with delete
0x0041B0A0 - locale0.cpp#200
0x0041A692 - locale0.cpp#55
0x0041A4B3 - locale0.cpp#69
0x004478A9 - xstart.cpp#50
0x0044784A
0x00453E02 - initexit.c#558
2) I wonder if you've found a simple reproduction of my previous occasional
issue documented here:
qc.borland.com/wc/qcmain.aspx
That problem appeared to involve clean up of locale/facets... I believe the
only way I avoided it was ultimately to get rid of my use of streams within
the particular program. (Use of streams has crept back in again, and have
been wondering if/when I might again get stung.)
Regards.
"Vaclav Cechura" < XXXX@XXXXX.COM >wrote in message
Quote

Call Tree:
0x004057EC(=project1.exe:0x01:0047EC) c:\program
files\borland\bds\4.0\include\dinkumware\xlocale#104
0x0041A948(=project1.exe:0x01:019948)
0x0040CBCA(=project1.exe:0x01:00BBCA)
0x00404126(=project1.exe:0x01:003126) c:\program
files\borland\bds\4.0\include\dinkumware\ios#125
0x00402FA9(=project1.exe:0x01:001FA9) c:\program
files\borland\bds\4.0\include\dinkumware\ostream#51
0x004023DE(=project1.exe:0x01:0013DE) c:\program
files\borland\bds\4.0\include\dinkumware\fstream#770


Any help appreciated.
Vaclav
 

{smallsort}

Re:Anybody can reproduce this BCB2006 error?

Further analysis of my problem results from your code indicates:
a "global_locale" entity is used by the (dinkumware) RTL, with a reference
count.
In this scenario, it appears that when the form is closed, the process
shutdown is also initiated, and a static routine, tidy_global(), is called,
which decrements a reference count, and then appears to delete the involved
items.
After that, the form objects destructor, where you have the local stream
definitions, is called, and that tries to access the "global_local",
requesting to increment its reference count - only its apparently gone.
I have not reviewed this thoroughly, but at a quick glance that's what
appears to be happening.
I don't suppose there's a chance anyone at CG could take a look at this, and
maybe even see something released to address this for BDS2006 - I'd really
like to be able to use streams in my bds2006 generated applications without
having "random" shutdown crashes/issues (see earlier parts of this thread
and QC38400 if interested.)
 

Re:Anybody can reproduce this BCB2006 error?

In article <4714a573$ XXXX@XXXXX.COM >,
"Vaclav Cechura" < XXXX@XXXXX.COM >wrote:
Quote
Using CodeGuard gives this information:
Error 00064. 0x100C30 (Thread 0x0634):
Method called on freed object: Attempt to access 8 byte(s) at 0x0105A8C0.
Dinkumware does some pointer arithmetic after freeing pointers. It's
been debated over in the language group whether or not this is allowed
by the standard. CodeGuard's assessment is correct, but the actual code
here seems to be harmless in actual implementation. We still haven't
decided what to do, but we may end up just special casing these
Dinkumware operations, so that CodeGuard will not be triggered in these
instances.
--
-David Dean
CodeGear C++ QA Engineer
<blogs.codegear.com/ddean/>
 

Re:Anybody can reproduce this BCB2006 error?

This is not one of the pointer arithmetic issues.
There appears to be an actual an attempt to increment a reference count on
an item that has been deleted, possibly due to the order in which initexit()
(???) items are invoked.
"David Dean [CodeGear]" < XXXX@XXXXX.COM >wrote in message
Quote
In article <4714a573$ XXXX@XXXXX.COM >,
"Vaclav Cechura" < XXXX@XXXXX.COM >wrote:

>Using CodeGuard gives this information:
>Error 00064. 0x100C30 (Thread 0x0634):
>Method called on freed object: Attempt to access 8 byte(s) at 0x0105A8C0.

Dinkumware does some pointer arithmetic after freeing pointers. It's
been debated over in the language group whether or not this is allowed
by the standard. CodeGuard's assessment is correct, but the actual code
here seems to be harmless in actual implementation. We still haven't
decided what to do, but we may end up just special casing these
Dinkumware operations, so that CodeGuard will not be triggered in these
instances.

--
-David Dean
CodeGear C++ QA Engineer
<blogs.codegear.com/ddean/>
 

Re:Anybody can reproduce this BCB2006 error?

I believe the pointer arithmetic items are generally reported as something
about a pointer outside of allocated buffer.
This is reported as "Method called on freed object in process...".
"David Dean [CodeGear]" < XXXX@XXXXX.COM >wrote in message
Quote
In article <4714a573$ XXXX@XXXXX.COM >,
"Vaclav Cechura" < XXXX@XXXXX.COM >wrote:

>Using CodeGuard gives this information:
>Error 00064. 0x100C30 (Thread 0x0634):
>Method called on freed object: Attempt to access 8 byte(s) at 0x0105A8C0.

Dinkumware does some pointer arithmetic after freeing pointers. It's
been debated over in the language group whether or not this is allowed
by the standard. CodeGuard's assessment is correct, but the actual code
here seems to be harmless in actual implementation. We still haven't
decided what to do, but we may end up just special casing these
Dinkumware operations, so that CodeGuard will not be triggered in these
instances.

--
-David Dean
CodeGear C++ QA Engineer
<blogs.codegear.com/ddean/>
 

Re:Anybody can reproduce this BCB2006 error?

"dhoke" < XXXX@XXXXX.COM >wrote:
Quote
Further analysis of my problem results from your code indicates:

a "global_locale" entity is used by the (dinkumware) RTL, with a reference
count.

In this scenario, it appears that when the form is closed, the process
shutdown is also initiated, and a static routine, tidy_global(), is called,
which decrements a reference count, and then appears to delete the involved
items.

After that, the form objects destructor, where you have the local stream
definitions, is called, and that tries to access the "global_local",
requesting to increment its reference count - only its apparently gone.
Sounds like a classic 'order of destruction' problem. You need to ensure
the form is destroyed before the statics start going.
Since the OP didn't show the code that creates and destroys the form,
it's difficult to confirm this, but I suspect that the auto-generated
skeleton needs altering so that the form is destroyed by the end of
main() (Or WinMain, or whatever it's been called today).
Alan Bellingham
--
Team Browns
ACCU Conference 2008: 2-5 April 2008 - Oxford (probably), UK
 

Re:Anybody can reproduce this BCB2006 error?

The form is the only form in the project and auto-created when the
application starts (at least for my version).
I close it with Alt-F4, which also initiates application shutdown. I'm
guessing using the little x in upper-right would yield similar results.
How would one adjust order of shutdown in this scenario to avoid this
problem?
"Alan Bellingham" < XXXX@XXXXX.COM >wrote in message
Quote
"dhoke" < XXXX@XXXXX.COM >wrote:

>Further analysis of my problem results from your code indicates:
>
>a "global_locale" entity is used by the (dinkumware) RTL, with a reference
>count.
>
>In this scenario, it appears that when the form is closed, the process
>shutdown is also initiated, and a static routine, tidy_global(), is
>called,
>which decrements a reference count, and then appears to delete the
>involved
>items.
>
>After that, the form objects destructor, where you have the local stream
>definitions, is called, and that tries to access the "global_local",
>requesting to increment its reference count - only its apparently gone.

Sounds like a classic 'order of destruction' problem. You need to ensure
the form is destroyed before the statics start going.

Since the OP didn't show the code that creates and destroys the form,
it's difficult to confirm this, but I suspect that the auto-generated
skeleton needs altering so that the form is destroyed by the end of
main() (Or WinMain, or whatever it's been called today).

Alan Bellingham
--
Team Browns
ACCU Conference 2008: 2-5 April 2008 - Oxford (probably), UK
 

Re:Anybody can reproduce this BCB2006 error?

dhoke wrote:
Quote
I close it with Alt-F4, which also initiates application shutdown. I'm
guessing using the little x in upper-right would yield similar results.
Um, no.
They both close Form1 which exits the message loop in WinMain.
Quote
How would one adjust order of shutdown in this scenario to avoid this
problem?
At the bottom of WinMain:
delete Form1; Form1=NULL;
return 0; // _exit executes here
}
 

Re:Anybody can reproduce this BCB2006 error?

"Bob Gonder" < XXXX@XXXXX.COM >wrote in message
Quote
dhoke wrote:

>I close it with Alt-F4, which also initiates application shutdown. I'm
>guessing using the little x in upper-right would yield similar results.

Um, no.
They both close Form1 which exits the message loop in WinMain.
exits the message loop because something somewhere sent a WM_QUIT message
(at least I think that's how it used to go)... I'm not sure I see a
functional difference since most programs I've seen are closing/existing
when they exit the primary message loop, VCL or otherwise, but OK.
Quote

>How would one adjust order of shutdown in this scenario to avoid this
>problem?

At the bottom of WinMain:

delete Form1; Form1=NULL;
return 0; // _exit executes here
}


Further questions:
So, does this mean, to be safe, one should, if one uses stream facilities,
always be sure that ALL forms in an application are deleted before returning
from WinMain?
And, what if one happens to have globally declared objects that might use
streams (say a logging facility that reports time of closure based on its
own destruction) - they presumably are destructed after the return from
WinMain() as well? Is there a way, and if so how does one adjust the order
of these relative to whatever calls that tidy_global() thingy?
And are there any other scenarios that the above thoughts are not covering
that should be taken into consideration?
 

Re:Anybody can reproduce this BCB2006 error?

Alan Bellingham wrote:
Quote

Sounds like a classic 'order of destruction' problem. You need to ensure
the form is destroyed before the statics start going.

Unfortunately, there is a real problem with globally constructed objects
and VCL. I'm not 100% sure why this problem exists, but I've experienced
that myself - global objects are destroyed before (main) form's
destructor has executed.
.a
 

Re:Anybody can reproduce this BCB2006 error?

In article <4714ed75$ XXXX@XXXXX.COM >,
"dhoke" < XXXX@XXXXX.COM >wrote:
Quote
I close it with Alt-F4, which also initiates application shutdown. I'm
guessing using the little x in upper-right would yield similar results.

How would one adjust order of shutdown in this scenario to avoid this
problem?
The OP states:
Quote
The error will disappear if all the code from TForm1's
destructor is moved to TForm1::FormClose() event
I'll take a closer look at the sample given. There are some other
instances of destructor order that I'm planning on investigating.
--
-David Dean
CodeGear C++ QA Engineer
<blogs.codegear.com/ddean/>
 

Re:Anybody can reproduce this BCB2006 error?

"David Dean [CodeGear]" < XXXX@XXXXX.COM >wrote in message
Quote
In article <4714ed75$ XXXX@XXXXX.COM >,
"dhoke" < XXXX@XXXXX.COM >wrote:

>I close it with Alt-F4, which also initiates application shutdown. I'm
>guessing using the little x in upper-right would yield similar results.
>
>How would one adjust order of shutdown in this scenario to avoid this
>problem?

The OP states:

>The error will disappear if all the code from TForm1's
>destructor is moved to TForm1::FormClose() event
Are you sure that the dtor of TForm1 is actually called?
I've had to move code into a CloseQuery() event because
of cases where the main form's dtor WASN'T called. I think
it was a windows logoff without shutting down the application
first. Hopefully that's not the issue here but you can test this
by writing to a file in the main form's dtor or something.
Quote
I'll take a closer look at the sample given. There are some other
instances of destructor order that I'm planning on investigating.
Generally a good thing considering VCL/STL problems in the past.
 

Re:Anybody can reproduce this BCB2006 error?

"Duane Hebert" < XXXX@XXXXX.COM >wrote in message
Quote


Are you sure that the dtor of TForm1 is actually called?
FWIW, At least in my case the dtor is called. I set breakpoints on the
tidy_global() routine, and on the TForm1 destructor.
I first broke at tidy_global(), and then subsequently broke at
TForm1::~TForm1().