- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The former code had a class that contained pointers to some objects, and the ctor of that class nulled out the pointers.
fee = NULL;
fi = NULL;
fo = NULL;
Where NULL is promoted to pointer of any type.
In the rewrite of the code the pointers were replaced with the class objects using same names in the code.
However, a programming error on my part, I left the former pointer NULL-ing code in the ctor.
The compiler did not produce an error, I do not know if it should or should not, but the result was:
The compiler promoted the NULL to the class object,
peformed a default copy operator,
then destroyed the NULL class object.
Is this a feature or bug???
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you declare a constructor "explicit" it can only be used for construction of an object, not for conversions.
Explanation here:
http://www.glenmccl.com/tip_023.htm
Is that what you want?
Judy
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you can show us a small test case that would help. NULL is usuallya macro for (void *)0 which can be converted to any pointer type. You should not be able to assign NULL to a class object unless there is anon explicitconstructorwith a pointer type argument or an appropriateconversion operator.Using the C++11new nullptr and nullptr_t typeis generally safer.
If the reference compiler (Gnu or Microsoft) doesn't give an error/warning then we cannot give oneeither. But it would be possible to add a remark if we can detect code that will likely lead to bad runtime behaviour.
Judy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>If the reference compiler (Gnu or Microsoft) doesn't give an error/warning then we cannot give oneeither.
Not so. you cannot get off that easy. If the code is wrong, you give the error.
The same argument above by you (Intel) can apply to the others as well.
Jim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
peformed a default copy operator,
then destroyed the NULL class object.
could you give more detail on the above? does your class have an overloaded operator to take "NULL" and convert to the class object? I could not duplicate it with a small test case:
cmd: icl /Od /EHsc t.cpp
[bash]#includeusing namespace std; class B { public: B():b(10) { cout << "in B()" << endl; }; ~B() { cout << "in ~B()" << endl; }; private: int b; }; class A { public: A() { p1 = NULL; cout << "in A(); P1= NULL" << endl; }; ~A(){ if (p1 != NULL) delete p1; cout << "in ~A()" << endl; }; void SetVars() { if (p1 == NULL) { cout << "in SetVars(): p1 = new B(); " << endl; p1 = new B(); } } private: B* p1; }; int main(int argc, char *argv[]) { cout << "start" << endl; A *t1 = new A; cout << "allocated A object" << endl; t1->SetVars(); delete t1; cout << "deleted A object" << endl; return 0; }
[/bash]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- {
- coutlt;lt;"start"lt;lt;endl;
- AanA;
- coutlt;lt;"instantiatedan Aobject"lt;lt;endl;
- anA = NULL;
- coutlt;lt;"NULL'ed an Aobject"lt;lt;endl;
- return0;
- }
I am not on my system, try the above. Your code did not assign NULL to an object.
Jim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
with this change, I got a compiler error:
C:>icl /Od /EHsc t.cpp
Intel C++ Compiler XE for applications running on IA-32, Version 12.1.1.258 Build 20111011
Copyright (C) 1985-2011 Intel Corporation. All rights reserved.
t.cpp
t.cpp(45): error: no suitable constructor exists to convert from "int" to "A"
t1 = NULL;
^
compilation aborted for t.cpp (code 2)
So icl did report an error for this simple case. is it the same for you with this testcase?
Jennifer
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My code did not.
I will see if I can make a simple reproducer.
A difference in my situation is that I used a class with a base class. The base class (I seem to recall) was the one getting ctor/dtor'd.
Jim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
class A {
to
class A : B {
and see what happens.
Jim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Is this a feature or bug???
...
Jim,could youprovide areal Test-Case that reproduces the problem?
I've created a very simple Test-Case and I was able to assign NULL to a class-based variable if I declare a
C++ operator '=' ( see Test-Case 3 ). The Test-Case is verified with four different C/C++ compilers.
My conclusion is as follows:
If a C/C++ compiler allows NULL assignment to some class-based automaticvariable, declared on the stack
or as global\staticand operator=( int ) is not declared, this is possiblya compiler'sbug.
...
class CTestA
{
public:
CTestA(){};
virtual ~CTestA(){};
// Test-Case 1
CTestA & operator=( CTestA &ta ){ return ( CTestA & )*this; };
// Test-Case 2
// CTestA & operator=( int &ia ){ return ( CTestA & )*this; };
// Test-Case 3
CTestA & operator=( int ia ){ return ( CTestA & )*this; };
};
class CTestB : public CTestA
{
public:
CTestB(){};
virtual ~CTestB(){};
// Test-Case 1
CTestB & operator=( CTestB &tb ){ return ( CTestB & )*this; };
// Test-Case 2
// CTestB & operator=( int &ib ){ return ( CTestB & )*this; };
// Test-Case 3
CTestB & operator=( int ib ){ return ( CTestB & )*this; };
};
class CTestC : CTestA
{
public:
CTestC(){};
virtual ~CTestC(){};
// Test-Case 1
CTestC & operator=( CTestC &tc ){ return ( CTestC & )*this; };
// Test-Case 2
// CTestC & operator=( int &ic ){ return ( CTestC & )*this; };
// Test-Case 3
CTestC & operator=( int ic ){ return ( CTestC & )*this; };
};
...
void main( void )
{
// MS C/C++ ( VS 2005 ) - Compiled
// Borland C++ v5.5.1 - Compiled
// MinGW v3.4.2- Compiled
// Turbo C++ v3.0.0 - Compiled if only one 'operator=( int ... )' is declared
// Failed if both operator=( int & ) and operator=( int ) are declared
// Error: 'CTestX::operator =(int)' cannot be distinguished from 'CTestX::operator =(int &)'
CTestA ta;
ta = NULL;
ta = ( int )NULL;
ta = ( int )0;
ta = ( int )0xFFFFFFFF;
CTestB tb;
tb = NULL;
tb = ( int )NULL;
tb = ( int )0;
tb = ( int )0xFFFFFFFF;
CTestC tc;
tc = NULL;
tc = ( int )NULL;
tc = ( int )0;
tc = ( int )0xFFFFFFFF;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is a new bug introduced today that prevented the attachment being uploaded. so I could not see your testcase.
could you paste the code to the response instead?
thanks,
Jennifer
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hope this works.
[cpp]// NULLtoClass.cpp : Defines the entry point for the console application. // #include "stdafx.h" #includeJim Dempsey// ** Intel ** // The following are typedefs, defines, class, struct, etc... // for missing headers in this shortened example program typedef __int64 Interlocked_t; // QuickThread.h typedef short qtPlacement; // QuickThread.h struct qtControl { int someStuff; void WaitTillDone() { return; } }; // QuickThread.h namespace qt { struct parallel_manifold_token { // member variables: void* Context; // User context void* This; // pointer to the data flow object // or // pointer to the resource flow object // member functions: // ctor parallel_manifold_token(); // dtor ~parallel_manifold_token(); }; struct parallel_manifold_context { // member variables: void* Context; // User context Interlocked_t maxTokens; // maximum number of tokens permitted volatile Interlocked_t nTokens; // number of tokens currently in system parallel_manifold_token* token_table; // table of tokens // member functions: // ctor parallel_manifold_context(); // dtor ~parallel_manifold_context(); // init function // sets User Context, maxTokens, allocates empty token_table[maxTokens] void init(void* _Context, Interlocked_t _maxTokens); parallel_manifold_context(void* _Context, Interlocked_t _maxTokens) { init(_Context, _maxTokens); } void addToken(int i, void* _Context, void* node); // retire token via address of some token in token_table // user code pass parallel_manifold_token* void retireToken(parallel_manifold_token* token); void WaitTillDone(); }; struct token_proxy { Interlocked_t x; // magic number referencing token in parallel_manifold_context }; struct parallel_resource_manifold; struct parallel_manifold_base { public: // member variables: parallel_manifold_context* context; parallel_manifold_token* token_table; // local copy of context->token_table Interlocked_t ringBufferSize; token_proxy* ringBuffer; volatile Interlocked_t fillIndexABA; volatile Interlocked_t emptyIndexABA; int nServerThreads; qtPlacement Placement; void (*server_f)(parallel_manifold_token*); parallel_resource_manifold* resource; qtControl control; bool take_stats; __int64 nFills; // updated when take_stats == true __int64 nTaskEnqueues; // updated when take_stats == true // member functions: // ctor parallel_manifold_base(); // dtor ~parallel_manifold_base(); // initializer void init( parallel_manifold_context* _context, parallel_resource_manifold* _resource = NULL); // ctor with args parallel_manifold_base( parallel_manifold_context* _context, parallel_resource_manifold* _resource = NULL ) { init(_context,_resource); } void WaitTillDone() { control.WaitTillDone(); } static void fillShellStatic(parallel_manifold_base*); virtual void run( qtPlacement _Placement, void (*_server_f)(parallel_manifold_token*), int _maxThreads = 0); virtual void fillShell(); virtual void fill(parallel_manifold_token* t); virtual void fill(parallel_manifold_token* t, size_t order); virtual parallel_manifold_token* empty(); }; // parallel_manifold_base // Ring buffers are Ordered or FIFO // Ordered: // Tokens may arrive in any order // Tokens are dispatched to the action task in circular sequence order // 0, 1, 2, ..., n, 0, 1, 2, ..., n, 0, 1, 2, ..., n, ... // // FIFO: // Tokens may arrive in any order // Tokens are dispatched in arrival sequence order // Single-Producer, Single-Consumer Ordered ring buffer struct parallel_manifold_SPSC_Ordered : parallel_manifold_base { parallel_manifold_SPSC_Ordered(); parallel_manifold_SPSC_Ordered( parallel_manifold_context* _context ); parallel_manifold_SPSC_Ordered( parallel_manifold_context* _context, parallel_resource_manifold* _resource ); ~parallel_manifold_SPSC_Ordered(); virtual void run( qtPlacement _Placement, void (*_server_f)(parallel_manifold_token*), int _maxThreads = 1); virtual void fillShell(); virtual void fill(parallel_manifold_token* t); virtual void fill(parallel_manifold_token* t, size_t order); virtual parallel_manifold_token* empty(); }; // Single-Producer, Single-Consumer FIFO struct parallel_manifold_SPSC_FIFO : parallel_manifold_base { parallel_manifold_SPSC_FIFO() {;} parallel_manifold_SPSC_FIFO( parallel_manifold_context* _context, parallel_resource_manifold* _resource = NULL ) { init(_context,_resource); } ~parallel_manifold_SPSC_FIFO() {;} virtual void run( qtPlacement _Placement, void (*_server_f)(parallel_manifold_token*), int _maxThreads = 1); virtual void fillShell(); virtual void fill(parallel_manifold_token* t); virtual void fill(parallel_manifold_token* t, size_t order); virtual parallel_manifold_token* empty(); }; // Multi-Producer, Single-Consumer Ordered struct parallel_manifold_MPSC_Ordered : parallel_manifold_base { parallel_manifold_MPSC_Ordered() {;} parallel_manifold_MPSC_Ordered( parallel_manifold_context* _context, parallel_resource_manifold* _resource = NULL ) { init(_context,_resource); } ~parallel_manifold_MPSC_Ordered() {;} virtual void run( qtPlacement _Placement, void (*_server_f)(parallel_manifold_token*), int _maxThreads = 1); virtual void fillShell(); virtual void fill(parallel_manifold_token* t); virtual void fill(parallel_manifold_token* t, size_t order); virtual parallel_manifold_token* empty(); }; // Multi-Producer, Single-Consumer FIFO struct parallel_manifold_MPSC_FIFO : parallel_manifold_base { parallel_manifold_MPSC_FIFO() {;} parallel_manifold_MPSC_FIFO( parallel_manifold_context* _context, parallel_resource_manifold* _resource = NULL ) { init(_context,_resource); } ~parallel_manifold_MPSC_FIFO() {;} virtual void run( qtPlacement _Placement, void (*_server_f)(parallel_manifold_token*), int _maxThreads = 1); virtual void fillShell(); virtual void fill(parallel_manifold_token* t); virtual void fill(parallel_manifold_token* t, size_t order); virtual parallel_manifold_token* empty(); }; // Single-Producer, Multi-Consumer, FIFO struct parallel_manifold_SPMC_FIFO : parallel_manifold_base { parallel_manifold_SPMC_FIFO() {;} parallel_manifold_SPMC_FIFO( parallel_manifold_context* _context, parallel_resource_manifold* _resource = NULL ) { init(_context,_resource); } ~parallel_manifold_SPMC_FIFO() {;} virtual void run( qtPlacement _Placement, void (*_server_f)(parallel_manifold_token*), int _maxThreads = 0); virtual void fillShell(); virtual void fill(parallel_manifold_token* t); virtual void fill(parallel_manifold_token* t, size_t order); virtual parallel_manifold_token* empty(); }; // Multi-Producer, Multi-Consumer, FIFO struct parallel_manifold_MPMC_FIFO : parallel_manifold_base { parallel_manifold_MPMC_FIFO() {;} parallel_manifold_MPMC_FIFO( parallel_manifold_context* _context, parallel_resource_manifold* _resource = NULL ) { init(_context,_resource); } ~parallel_manifold_MPMC_FIFO() {;} virtual void run( qtPlacement _Placement, void (*_server_f)(parallel_manifold_token*), int _maxThreads = 0); virtual void fillShell(); virtual void fill(parallel_manifold_token* t); virtual void fill(parallel_manifold_token* t, size_t order); virtual parallel_manifold_token* empty(); }; #if 0 struct x : parallel_manifold_base { x() {;} x( parallel_manifold_context* _context, parallel_resource_manifold* _resource = NULL ) { init(_context,_resource); } ~x() {;} virtual void run( qtPlacement _Placement, void (*_server_f)(parallel_manifold_token*), int _maxThreads = 0); virtual void fillShell(); virtual void fill(parallel_manifold_token* t); virtual void fill(parallel_manifold_token* t, size_t order); virtual parallel_manifold_token* empty(); }; #endif struct parallel_manifold_functor_token_list { void (*server_f)(parallel_manifold_functor_token_list*); intptr_t nTokens; parallel_manifold_token* token_list[]; }; parallel_manifold_functor_token_list* parallel_manifold_functor_token_list_new( void (*_server_f)(parallel_manifold_functor_token_list*), size_t _nTokens); void parallel_manifold_functor_token_list_delete(parallel_manifold_functor_token_list* p); struct resource_token_proxy : token_proxy { parallel_manifold_base* pmb; }; struct parallel_resource_manifold { // member variables: parallel_manifold_context* context; parallel_manifold_token* token_table; // local copy of context->token_table Interlocked_t ringBufferSize; resource_token_proxy* ringBuffer; volatile Interlocked_t fillIndexABA; volatile Interlocked_t emptyIndexABA; bool take_stats; __int64 nFills; // updated when take_stats == true __int64 nTaskEnqueues; // updated when take_stats == true parallel_resource_manifold(); ~parallel_resource_manifold(); // init function void init(parallel_manifold_context* _context); virtual void fillShell(); virtual void fill(parallel_manifold_token* t); virtual void fill(parallel_manifold_token* t, size_t order); virtual parallel_manifold_token* empty(); parallel_manifold_token* empty(parallel_manifold_base* pmb); }; // struct parallel_resource_manifold struct parallel_multi_port_manifold_port { parallel_manifold_context* context; parallel_manifold_token* token_table; // local copy of context->token_table Interlocked_t ringBufferSize; }; struct parallel_multi_port_manifold_base { parallel_manifold_context* context; parallel_manifold_token* token_table; // local copy of context->token_table Interlocked_t ringBufferSize; token_proxy* ringBuffer; volatile Interlocked_t fillIndexABA; volatile Interlocked_t emptyIndexABA; int nServerThreads; qtPlacement Placement; void (*server_f)(parallel_manifold_token*); qtControl control; bool take_stats; __int64 nFills; // take_stats __int64 nTaskEnqueues; // take_stats parallel_multi_port_manifold_base(); ~parallel_multi_port_manifold_base(); void init( parallel_manifold_context* _context, qtPlacement _Placement, void (*_server_f)(parallel_manifold_token*), int _maxThreads = 0); }; // struct parallel_multi_port_manifold_base struct parallel_multi_port_manifold : parallel_multi_port_manifold_base { void* vp; }; parallel_manifold_base::parallel_manifold_base() { return; } parallel_manifold_base::~parallel_manifold_base() { return; } void parallel_manifold_base::init(parallel_manifold_context * ctx, parallel_resource_manifold * mn) { return; } void parallel_manifold_base::run(qtPlacement, void (__cdecl*fn)(struct qt::parallel_manifold_token *), int n) { return; } void parallel_manifold_base::fillShell() { return; } void parallel_manifold_base::fill(parallel_manifold_token * t, unsigned int n) { return; } void parallel_manifold_base::fill(parallel_manifold_token *t) { return; } parallel_manifold_token * parallel_manifold_base::empty() { return NULL; } void parallel_manifold_SPSC_FIFO::run(qtPlacement, void (*fn)(parallel_manifold_token *), int n) { return; } void parallel_manifold_SPSC_FIFO::fillShell() { return; } void __thiscall qt::parallel_manifold_SPSC_FIFO::fill(parallel_manifold_token * t, unsigned int n) { return; } void __thiscall qt::parallel_manifold_SPSC_FIFO::fill(parallel_manifold_token * t) { return; } parallel_manifold_token *parallel_manifold_SPSC_FIFO::empty() { return NULL; } } // namespace qt using namespace std; using namespace qt; class FooManager { void* stuff; }; class Foos { public: Foos(int ep, FooManager* fm); virtual ~Foos(); void StartFooProcessing(); void StopFoo(); void writeBuffer(parallel_manifold_token* token); void showBug(); protected: // Use this for L7 Foo void SetupFoo(int ep); void FooProcess(); private: int endpoint; int numberToken; public: FooManager* flowMgr; volatile int simulateNewPacket; // flow diagram: // (initialization) // | // |________ // V (top) parallel_manifold_SPSC_FIFO input;// | // |-------->| // V | parallel_manifold_SPSC_FIFO process;// | // ||------->| // VV | parallel_manifold_SPSC_FIFO output;// | }; Foos::Foos(int n,class FooManager *fm) { return; } Foos::~Foos() { return; } void Foos::showBug() { input = NULL; } int _tmain(int argc, _TCHAR* argv[]) { FooManager* flowMgr = new FooManager; Foos* flow = new Foos(0,flowMgr); flow->showBug(); return 0; } [/cpp]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's because your class parallel_manifold_SPSC_FIFO has a constructor:
parallel_manifold_SPSC_FIFO( parallel_manifold_context* _context, parallel_resource_manifold* _resource = NULL )
so it can create an object from NULL. it does not like a bug to me.
Let me attach the simpler test here t.cpp.
Jennifer
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The required argument is (was) missing in the
input = NULL;
and there is no operator=()
both of which should have been rquired.
What this appears to have done is cast
(void*)0
into
(parallel_manifold_context*)0
a) Then assume an implied conversion operator. Or
b) implied ctor with argument of the point.
Actually I think in this case it would be better called a dereferencing copy operator.
There is no conversion operator (for a), and the syntax is not right to instigate a ctor.
An additional curiosity is the dtor is also run immediately after the assignment, therefore indicating the statement is performing an operator=() using a temporary object created from a (missing) conversion operator(parallel_manifold_SPSC_FIFO)(parallel_manifold_context*), also not specified.
To me, this seems like a bug.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The strange thing is if I add the "A& operator=(A& in){}", both icl & cl emits an error below instead:
t.cpp(47): error: no operator "=" matches these operands
operand types are: B = int
bobj = NULL; // should error here
^
Jennifer
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To me, this seems like a bug.
...
Jim Dempsey
Hello everybody,
I've just completedCompilations with 4 different C/C++ compilers. I'll do Runtime verifications( debugging ) tomorrow.
So, even a Turbo C++ v3.0.0 compiled the Test-Casewith somemodifications. Here is its output:
Turbo C++ Version 3.00 Copyright (c) 1992 Borland International
tcctes~1.cpp:
Turbo Link Version 5.0 Copyright (c) 1992 Borland International
Error: Undefined symbol parallel_manifold_base::run(short,void(far*)(parallel_manifold_token near*),int) in module tcctes~1.cpp
Available memory 3402856
TccTestApp -1 error(s), 0 warning(s)
Note: Please don't pay attention for a linking error. This is a different "story".
SUMMARY:
// MS C/C++ ( VS 2005 ) - Compiled \ Modifications - 0 \ One Warning
struct parallel_manifold_functor_token_list
{
...
parallel_manifold_token* token_list[];
// Warning C4200: nonstandard extension used : zero-sized array in struct/union
// Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array
};
// Borland C++ v5.5.1 - Compiled \ Modifications - 3 \ No Warnings
//Doesn't support:
'intptr_t'
'__thiscall'
...
struct parallel_manifold_functor_token_list
{
void (*server_f)(parallel_manifold_functor_token_list*);
// intptr_t nTokens;
int nTokens;
parallel_manifold_token* token_list[];
};
...
void /*__thiscall*/ qt::parallel_manifold_SPSC_FIFO::fill(parallel_manifold_token * t, unsigned int n)
{ return; }
void /*__thiscall*/ qt::parallel_manifold_SPSC_FIFO::fill(parallel_manifold_token * t)
{ return; }
...
// MinGW v3.4.2 - Compiled \ Modifications - 2 \ No Warnings
//Doesn't support
'__thiscall'
...
void /*__thiscall*/ qt::parallel_manifold_SPSC_FIFO::fill(parallel_manifold_token * t, unsigned int n)
{ return; }
void /*__thiscall*/ qt::parallel_manifold_SPSC_FIFO::fill(parallel_manifold_token * t)
{ return; }
...
// Turbo C++ v3.0.0 - Compiled \ Modifications ->10\ No Warnings
//Doesn't support:
'iostream'
'__int64'
'namespace qt'
'qt::parallel_manifold_token'
'using namespace qt'
'using namespace std'
'bool'
'__thiscall'
'void parallel_manifold_functor_token_list_delete(parallel_manifold_functor_token_list* p)' commented
'void parallel_manifold_base::run(qtPlacement, void (__cdecl*fn)(struct /*qt::*/parallel_manifold_token *), int n)' commented ( creates a linking error )
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Correct. The trailing (second argument) is defaulted.
>> The required argument is (was) missing in the
>> input = NULL;
No. NULL is used for the required (first) argument and the default argument valueis used for the second.
>> and there is no operator=()
Every class has an implicit assignment operator generated by the compilerif the user does not declare one explicitly.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hope you have read Judy's explaination.
Also I checked with our compiler FE experts,and below is my understanding when compiler see "input = NULL;"
1. "NULL" is a valid value for any pointer variable (as an init value).
2. compiler created a tempoary object with "NULL" based on ctor A(B*p, C*p2=NULL) ---- the 2nd parameter is optional.
3. compiler uses the "default assignment operator" generated by the compiler itself to assign the temp object to variable "input" when there is no assignment operator overloading.
4. in my testcase the overloading assignement operator is "B& operator (B& in)", but it should be "B& operator (B const & in)" instead. if changing to the later one, the compiler will not issue the error.
One rule worth note here from our compiler expert and this explains why "B& operator (B const & in)" is needed:
C++ overload resolution has a special rule: a reference-to-non-const parameter is not allowed to bind to a temporary object.
Jennifer
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>To me, this seems like a bug.
>>...
>>Jim Dempsey
I don't see any problems with C/C++ compilers I tested. I would rather change how 'input' member is
initialized. Here is an example:
...
void Foos::showBug()
{
// input = NULL;
input.init( NULL );
// input.init( NULL, NULL );
}
...
When you try to assign NULL to 'input' member two default C++ operators '='are called:
...
qt::parallel_manifold_SPSC_FIFO::operator=
...
004B8A5A call qt::parallel_manifold_base::operator= (4A55CDh)
...
004B8A75 ret 4
...
Here is a screenshot:
Here is a summary\outputs of my tests:
// Test-Case 1: Output without a C++ operator=( int ) in a parallel_manifold_SPSC_FIFO class
new FooManager
new Foos( 0, flowMgr )
Foos::Foos(int n,class FooManager *fm)
Foos::showBug()
input = NULL
parallel_manifold_SPSC_FIFO::parallel_manifold_SPSC_FIFO( ... )
parallel_manifold_base::init( ... )
delete flow
Foos::~Foos()
delete flowMgr
// Test-Case 2: Output if a C++ operator=( int ) added in a parallel_manifold_SPSC_FIFO class
new Foos( 0, flowMgr )
Foos::Foos(int n,class FooManager *fm)
Foos::showBug()
input = NULL
delete flow
Foos::~Foos()
delete flowMgr
...
struct parallel_manifold_SPSC_FIFO : parallel_manifold_base
{
...
parallel_manifold_SPSC_FIFO & operator=( int )
{
return ( parallel_manifold_SPSC_FIFO & )*this;
};
...
};
...
// Test-Case 3: Output if a call to input.init( ... ) added instead of input = NULL assignment
// Without a C++ operator=( int ) // With a C++ operator=( int )
new FooManager new FooManager
new Foos( 0, flowMgr ) new Foos( 0, flowMgr )
Foos::Foos(int n,class FooManager *fm)Foos::Foos(int n,class FooManager *fm)
Foos::showBug() Foos::showBug()
parallel_manifold_base::init( ... ) parallel_manifold_base::init( ... )
delete flow delete flow
Foos::~Foos() Foos::~Foos()
delete flowMgr delete flowMgr
They are identical and this is right.
...
void Foos::showBug()
{
CrtPrintf( RTU("Foos::showBug()\n") );
// CrtPrintf( RTU("input = NULL\n") );
// input = NULL;
input.init( NULL );
// input.init( NULL, NULL );
}
...
// Disassembler Codes - for Test-Case 1
...
qt::parallel_manifold_SPSC_FIFO::operator=
004B8A30 push ebp
004B8A31 mov ebp,esp
004B8A33 sub esp,0CCh
004B8A39 push ebx
004B8A3A push esi
004B8A3B push edi
004B8A3C push ecx
004B8A3D lea edi,[ebp-0CCh]
004B8A43 mov ecx,33h
004B8A48 mov eax,0CCCCCCCCh
004B8A4D rep stos dword ptr es:[edi]
004B8A4F pop ecx
004B8A50 mov dword ptr [ebp-8],ecx
004B8A53 mov eax,dword ptr [__that]
004B8A56 push eax
004B8A57 mov ecx,dword ptr [this]
004B8A5A call qt::parallel_manifold_base::operator= (4A55CDh)
004B8A5F mov eax,dword ptr [this]
004B8A62 pop edi
004B8A63 pop esi
004B8A64 pop ebx
004B8A65 add esp,0CCh
004B8A6B cmp ebp,esp
004B8A6D call @ILT+36765(__RTC_CheckEsp) (4ADFA2h)
004B8A72 mov esp,ebp
004B8A74 pop ebp
004B8A75 ret 4
...

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page