S
Scott Niu
Hi,
I have this following simple c++ program, it will produce memory leak
( see what I did below ).
My observation also showed that:
There will be a mem leak when all the 3 conditions are true:
1. CallControlData does not provide a operator=
2. INUserHandle's operator= returns a object instead of a reference
3. Use CC -g main_leak.C instead of CC main_leak.C to compile.
You change any of the above condition, there will be NO mem leak.
The CC I used is Sun's /opt/SUNWspro/SC4.2/bin/CC.
If I use g++, and if all the above 3 conditions are true, there will be
memory leak. Besides that, even we
don't use g++ -g option, there will still be memory leak.
Can somebody explain this ?
Source of my main_leak.C is:
#include <iostream.h>
#define NULL 0
const int Size = 10;
short printlevel = 0;
class HandleBase
{
public:
int i;
};
class INUserHandle
{
public:
INUserHandle()
{
cout << "Entering INUserHandle()" << endl;
pchar = new char[Size];
impl = new HandleBase;
cout << "this = "<< this << endl;
cout << "Leaving INUserHandle()" << endl;
}
INUserHandle(const INUserHandle& handle)
char ( NULL)
, impl( NULL )
{
cout << "Entering INUserHandle(constINUserHandle&)" << endl;
pchar = new char[Size];
impl = new HandleBase(*handle.impl);
for ( int i = 0; i < Size ; i++ )
{
pchar = handle.pchar;
}
cout << "this = "<< this << endl;
cout << "Leaving INUserHandle(constINUserHandle&)" << endl;
}
// Note here, that one is returning obj, one is returning reference.
//INUserHandle& operator=(const INUserHandle& handle)
INUserHandle operator=(const INUserHandle& handle)
{
cout << "Entering INUserHandle:perator= "<< endl;
if( this != &handle ) {
delete [] pchar;
pchar = new char[Size];
delete impl;
impl = new HandleBase(*handle.impl);
for ( int i = 0; i < Size ; i++ )
{
pchar = handle.pchar;
}
}
cout << "Leaving INUserHandle:perator= "<< endl;
return *this;
}
~INUserHandle()
{
cout << "Entering ~INUserHandle()." << endl;
delete [] pchar ;
delete impl;
cout << "this = "<< this << endl;
cout << "Leaving ~INUserHandle()." << endl;
}
public:
char *pchar;
HandleBase *impl;
};
class CallControlData {
public:
public:
INUserHandle handle;
};
class CallControlData_assignment {
public:
CallControlData_assignment& operator=(const
CallControlData_assignment& cdata_ass)
{
cout << "Entering CallControlData_assignment:pertor= " <<
endl;
handle = cdata_ass.handle;
cout << "Leaving CallControlData_assignment:pertor= " <<
endl;
return *this;
}
public:
INUserHandle handle;
};
void f()
{
CallControlData cdata1;
CallControlData cdata2;
cdata1 = cdata2;
//CallControlData_assignment cdata_ass1;
//CallControlData_assignment cdata_ass2;
//cdata_ass1 = cdata_ass2;
};
void g()
{
f();
};
int
main()
{
g();
//while ( 1 ) {int i;};
return 1;
}
What I did:
1. compile it.
2. run dbx a.out
3. in dbx prompt, type check -memuse
4. in dbx prompt, type run
$>/opt/SUNWspro/SC4.2/bin/CC -g main_leak.C
$>
$>dbx a.out
The major new features of this release relative to 3.2 are:
o The Collector now supports MT applications (see `help collectormt')
o Runtime checking (RTC) is supported with fork/exec/attach (see `help
rtc attach' for details)
o RTC has an API for allocators (see `help rtc api')
o New command `regs' to print current value of registers (see `help regs')
o New command `showblock' to give details about heap block (see `help
showblock')
o Enhanced `pathmap' command (see `help pathmap')
o New dbxenv variable 'language_mode' (see `help dbxenv' under
`language_mode')
o New dbxenv variable 'output_inherited_members' (ee `help dbxenv' under
`output_inherited_members')
o Two new dbx read-only variables: $helpfile and $helpfile_html (see `help
help')
o New -v (verbose) flag to the `module' and `modules' commands
(see `help module' and `help modules')
o New +r flag to print and display commands (see `help print')
o Default value of dbxenv variable `scope_look_aside' has been changed
to on (see `help dbxenv' under scope_look_aside and `help scope')
o New `inobject' event for support of `stop inobject <c++_obj_exp>'
(see `help c++ inobject' and `help event specification')
o `inclass' event now supports template classes (see `help c++ inclass' and
`help event specification')
o `stop at <lineno>' now supports C++ template definitions as well as
C++ inlined functions defined in header files (see `help event
specification'
under `at' event)
o Support for new C++ operators: `const_cast', `dynamic_cast',
`reinterpret_cast', and `static_cast'
o Support for new C++ `typeid' operator
o An HTML version of the help file is available (see `help help')
See also `help changes32'
The major new features of 3.2 (SPARCWorks 3.1) relative to 3.1 are:
o Objective C support (see `help ObjC')
o Fortran 90 support (see `help fortran')
o Runtime checking (RTC) gives information about memory usage
Reading symbolic information for a.out
Reading symbolic information for rtld /usr/lib/ld.so.1
Reading symbolic information for libm.so.1
Reading symbolic information for libC.so.5
Reading symbolic information for libw.so.1
Reading symbolic information for libc.so.1
Reading symbolic information for libdl.so.1
Reading symbolic information for libc_psr.so.1
(dbx)
(dbx)
(dbx) check -memuse
memuse checking - ON
(dbx) run
Running: a.out
(process id 21043)
Reading symbolic information for librtc.so
Skipping libm.so.1, already read
Skipping libC.so.5, already read
Skipping libw.so.1, already read
Skipping libc.so.1, already read
Skipping libdl.so.1, already read
Skipping libc_psr.so.1, already read
Enabling Error Checking... done
Entering INUserHandle()
this = 0xeffff314
Leaving INUserHandle()
Entering INUserHandle()
this = 0xeffff30c
Leaving INUserHandle()
Entering INUserHandle:perator=
Leaving INUserHandle:perator=
Entering INUserHandle(constINUserHandle&)
this = 0xeffff29c
Leaving INUserHandle(constINUserHandle&)
Entering ~INUserHandle().
this = 0xeffff30c
Leaving ~INUserHandle().
Entering ~INUserHandle().
this = 0xeffff314
Leaving ~INUserHandle().
Checking for memory leaks...
Actual leaks report (actual leaks: 2 total size: 14 bytes)
Total Num of Leaked Allocation call stack
Size Blocks Block
Address
====== ====== ========== =======================================
10 1 0x22848 operator new < INUserHandle::INUserHandle <
INUserHandle:perator = < CallControlData:perator = < f < g < main
4 1 0x23238 operator new < INUserHandle::INUserHandle <
INUserHandle:perator = < CallControlData:perator = < f < g < main
Possible leaks report (possible leaks: 0 total size: 0 bytes)
Checking for memory use...
Blocks in use report (blocks in use: 0 total size: 0 bytes)
execution completed, exit code is 1
(dbx) quit
$>
I have this following simple c++ program, it will produce memory leak
( see what I did below ).
My observation also showed that:
There will be a mem leak when all the 3 conditions are true:
1. CallControlData does not provide a operator=
2. INUserHandle's operator= returns a object instead of a reference
3. Use CC -g main_leak.C instead of CC main_leak.C to compile.
You change any of the above condition, there will be NO mem leak.
The CC I used is Sun's /opt/SUNWspro/SC4.2/bin/CC.
If I use g++, and if all the above 3 conditions are true, there will be
memory leak. Besides that, even we
don't use g++ -g option, there will still be memory leak.
Can somebody explain this ?
Source of my main_leak.C is:
#include <iostream.h>
#define NULL 0
const int Size = 10;
short printlevel = 0;
class HandleBase
{
public:
int i;
};
class INUserHandle
{
public:
INUserHandle()
{
cout << "Entering INUserHandle()" << endl;
pchar = new char[Size];
impl = new HandleBase;
cout << "this = "<< this << endl;
cout << "Leaving INUserHandle()" << endl;
}
INUserHandle(const INUserHandle& handle)
char ( NULL)
, impl( NULL )
{
cout << "Entering INUserHandle(constINUserHandle&)" << endl;
pchar = new char[Size];
impl = new HandleBase(*handle.impl);
for ( int i = 0; i < Size ; i++ )
{
pchar = handle.pchar;
}
cout << "this = "<< this << endl;
cout << "Leaving INUserHandle(constINUserHandle&)" << endl;
}
// Note here, that one is returning obj, one is returning reference.
//INUserHandle& operator=(const INUserHandle& handle)
INUserHandle operator=(const INUserHandle& handle)
{
cout << "Entering INUserHandle:perator= "<< endl;
if( this != &handle ) {
delete [] pchar;
pchar = new char[Size];
delete impl;
impl = new HandleBase(*handle.impl);
for ( int i = 0; i < Size ; i++ )
{
pchar = handle.pchar;
}
}
cout << "Leaving INUserHandle:perator= "<< endl;
return *this;
}
~INUserHandle()
{
cout << "Entering ~INUserHandle()." << endl;
delete [] pchar ;
delete impl;
cout << "this = "<< this << endl;
cout << "Leaving ~INUserHandle()." << endl;
}
public:
char *pchar;
HandleBase *impl;
};
class CallControlData {
public:
public:
INUserHandle handle;
};
class CallControlData_assignment {
public:
CallControlData_assignment& operator=(const
CallControlData_assignment& cdata_ass)
{
cout << "Entering CallControlData_assignment:pertor= " <<
endl;
handle = cdata_ass.handle;
cout << "Leaving CallControlData_assignment:pertor= " <<
endl;
return *this;
}
public:
INUserHandle handle;
};
void f()
{
CallControlData cdata1;
CallControlData cdata2;
cdata1 = cdata2;
//CallControlData_assignment cdata_ass1;
//CallControlData_assignment cdata_ass2;
//cdata_ass1 = cdata_ass2;
};
void g()
{
f();
};
int
main()
{
g();
//while ( 1 ) {int i;};
return 1;
}
What I did:
1. compile it.
2. run dbx a.out
3. in dbx prompt, type check -memuse
4. in dbx prompt, type run
$>/opt/SUNWspro/SC4.2/bin/CC -g main_leak.C
$>
$>dbx a.out
The major new features of this release relative to 3.2 are:
o The Collector now supports MT applications (see `help collectormt')
o Runtime checking (RTC) is supported with fork/exec/attach (see `help
rtc attach' for details)
o RTC has an API for allocators (see `help rtc api')
o New command `regs' to print current value of registers (see `help regs')
o New command `showblock' to give details about heap block (see `help
showblock')
o Enhanced `pathmap' command (see `help pathmap')
o New dbxenv variable 'language_mode' (see `help dbxenv' under
`language_mode')
o New dbxenv variable 'output_inherited_members' (ee `help dbxenv' under
`output_inherited_members')
o Two new dbx read-only variables: $helpfile and $helpfile_html (see `help
help')
o New -v (verbose) flag to the `module' and `modules' commands
(see `help module' and `help modules')
o New +r flag to print and display commands (see `help print')
o Default value of dbxenv variable `scope_look_aside' has been changed
to on (see `help dbxenv' under scope_look_aside and `help scope')
o New `inobject' event for support of `stop inobject <c++_obj_exp>'
(see `help c++ inobject' and `help event specification')
o `inclass' event now supports template classes (see `help c++ inclass' and
`help event specification')
o `stop at <lineno>' now supports C++ template definitions as well as
C++ inlined functions defined in header files (see `help event
specification'
under `at' event)
o Support for new C++ operators: `const_cast', `dynamic_cast',
`reinterpret_cast', and `static_cast'
o Support for new C++ `typeid' operator
o An HTML version of the help file is available (see `help help')
See also `help changes32'
The major new features of 3.2 (SPARCWorks 3.1) relative to 3.1 are:
o Objective C support (see `help ObjC')
o Fortran 90 support (see `help fortran')
o Runtime checking (RTC) gives information about memory usage
Reading symbolic information for a.out
Reading symbolic information for rtld /usr/lib/ld.so.1
Reading symbolic information for libm.so.1
Reading symbolic information for libC.so.5
Reading symbolic information for libw.so.1
Reading symbolic information for libc.so.1
Reading symbolic information for libdl.so.1
Reading symbolic information for libc_psr.so.1
(dbx)
(dbx)
(dbx) check -memuse
memuse checking - ON
(dbx) run
Running: a.out
(process id 21043)
Reading symbolic information for librtc.so
Skipping libm.so.1, already read
Skipping libC.so.5, already read
Skipping libw.so.1, already read
Skipping libc.so.1, already read
Skipping libdl.so.1, already read
Skipping libc_psr.so.1, already read
Enabling Error Checking... done
Entering INUserHandle()
this = 0xeffff314
Leaving INUserHandle()
Entering INUserHandle()
this = 0xeffff30c
Leaving INUserHandle()
Entering INUserHandle:perator=
Leaving INUserHandle:perator=
Entering INUserHandle(constINUserHandle&)
this = 0xeffff29c
Leaving INUserHandle(constINUserHandle&)
Entering ~INUserHandle().
this = 0xeffff30c
Leaving ~INUserHandle().
Entering ~INUserHandle().
this = 0xeffff314
Leaving ~INUserHandle().
Checking for memory leaks...
Actual leaks report (actual leaks: 2 total size: 14 bytes)
Total Num of Leaked Allocation call stack
Size Blocks Block
Address
====== ====== ========== =======================================
10 1 0x22848 operator new < INUserHandle::INUserHandle <
INUserHandle:perator = < CallControlData:perator = < f < g < main
4 1 0x23238 operator new < INUserHandle::INUserHandle <
INUserHandle:perator = < CallControlData:perator = < f < g < main
Possible leaks report (possible leaks: 0 total size: 0 bytes)
Checking for memory use...
Blocks in use report (blocks in use: 0 total size: 0 bytes)
execution completed, exit code is 1
(dbx) quit
$>