weird vc8 auto_ptr bug, spent a day trying to find out what's wrong
-
it's quite easy to reproduce. #include #include class A { int i; public: A() : i(1) {} virtual ~A() { std::cout << "in ~A()\n"; } }; std::auto_ptr bad_function() { return new A(); } int main() { std::auto_ptr bug = bad_function(); bug.reset(); return 0; } the thing is although auto_ptr(pointer_type) is explicit, vc8 compiler somehow finds a way to cast A* to auto_ptr. what's even worse is that it's doing this by dereferencing pointer before assinging to auto_ptr::_Myptr. in situation when object has virtual functions this makes vitrual functions table pointer __vfptr to contain a pointer to the first virtual function of the class (A::'scalar deleting destrustor' in this example) instead of A::vftable. so when you call any virtual fuction (virtual destructor in this case) control goes to a random address and you get 'Access violation'. in my case things were worse since auto_ptr was a global variable and program crashed on exit so it was quite hard to detect when things started to go wrong. of course any(?) other compiler will easily spot the problem. 'return new A()' must be 'return std::auto_ptr(new A())' instead. i just wonder why vc8 behaves this way... ps. yes, i used google and hadn't found anything helpful. pss. yes, i have SP1 installed and i don't use any STL replacements. Constantin Bryzgalin http://www.oneclicktools.com
-
it's quite easy to reproduce. #include #include class A { int i; public: A() : i(1) {} virtual ~A() { std::cout << "in ~A()\n"; } }; std::auto_ptr bad_function() { return new A(); } int main() { std::auto_ptr bug = bad_function(); bug.reset(); return 0; } the thing is although auto_ptr(pointer_type) is explicit, vc8 compiler somehow finds a way to cast A* to auto_ptr. what's even worse is that it's doing this by dereferencing pointer before assinging to auto_ptr::_Myptr. in situation when object has virtual functions this makes vitrual functions table pointer __vfptr to contain a pointer to the first virtual function of the class (A::'scalar deleting destrustor' in this example) instead of A::vftable. so when you call any virtual fuction (virtual destructor in this case) control goes to a random address and you get 'Access violation'. in my case things were worse since auto_ptr was a global variable and program crashed on exit so it was quite hard to detect when things started to go wrong. of course any(?) other compiler will easily spot the problem. 'return new A()' must be 'return std::auto_ptr(new A())' instead. i just wonder why vc8 behaves this way... ps. yes, i used google and hadn't found anything helpful. pss. yes, i have SP1 installed and i don't use any STL replacements. Constantin Bryzgalin http://www.oneclicktools.com
I've always thought that at warning level 4, a good compiler would be one that says, return type does not match declaration. Default cast implemented. At least at that point you have an indication that maybe the compiler is doing something different than what you originally intended. :)
Chris Meech I am Canadian. [heard in a local bar]
-
I've always thought that at warning level 4, a good compiler would be one that says, return type does not match declaration. Default cast implemented. At least at that point you have an indication that maybe the compiler is doing something different than what you originally intended. :)
Chris Meech I am Canadian. [heard in a local bar]
the problem is actually that there's no default cast in this case, appropriate constructor is 'explicit'. returning different type with implicit conversion to right one is absolutely legal in c++. no reason for warnings, since compilers is not 'doing something different than what you originally intended'. it does exactly what developer expects. i just made a mistake expecting pointer to be automatically converted to auto_ptr. compiler had to fail here, but instead it did something unexpected. violating standard actually, i think.
Constantin Bryzgalin http://www.oneclicktools.com
-
it's quite easy to reproduce. #include #include class A { int i; public: A() : i(1) {} virtual ~A() { std::cout << "in ~A()\n"; } }; std::auto_ptr bad_function() { return new A(); } int main() { std::auto_ptr bug = bad_function(); bug.reset(); return 0; } the thing is although auto_ptr(pointer_type) is explicit, vc8 compiler somehow finds a way to cast A* to auto_ptr. what's even worse is that it's doing this by dereferencing pointer before assinging to auto_ptr::_Myptr. in situation when object has virtual functions this makes vitrual functions table pointer __vfptr to contain a pointer to the first virtual function of the class (A::'scalar deleting destrustor' in this example) instead of A::vftable. so when you call any virtual fuction (virtual destructor in this case) control goes to a random address and you get 'Access violation'. in my case things were worse since auto_ptr was a global variable and program crashed on exit so it was quite hard to detect when things started to go wrong. of course any(?) other compiler will easily spot the problem. 'return new A()' must be 'return std::auto_ptr(new A())' instead. i just wonder why vc8 behaves this way... ps. yes, i used google and hadn't found anything helpful. pss. yes, i have SP1 installed and i don't use any STL replacements. Constantin Bryzgalin http://www.oneclicktools.com
A college of mine found the same problem a while ago 30 March, 2006, here is the explaination (fix) in a correspondance to P.J. Plauger. Text in bold is the important part. :) Problem with auto_ptr in Microsoft VC8 Recently I was foolish enough to write the something along the lines of
class B
{
public:
void f();
};.
.auto_ptr<B> apB;
apB = new B;
apB->f();This compiled with Microsoft VC8 but would crash when attempting to call the member function B::f() via the auto_ptr. The problem is that the constructor auto_ptr_ref::auto_ptr_ref(void *) is not 'explicit' and as a result the compiler constructed an auto_ptr_ref from my 'new B' and used that to assign to apB. I have modified my copy of the 'memory' header file to make the constructor explicit which prevents the compilation from succeeding and forcing the more successful
apB = auto_ptr<B>(new B);
If, as I suppose is likely, you are already aware of this problem I apologise for wasting your time. I've known about the bug, but not your fix. Our code works fine on gcc and EDG-based compilers, but misbehaves as you describe for VC++. I've added your fix to our baseline -- if it survives testing for the next week on all of our platforms for the next week or so, it'll be part of our next (imminent) release. I'll also feed it back to Microsoft. Keep up the good work Thanks very much. P.J. Plauger I would expect that at some time in the future the fix is either made perminent or an alternative fix is introduced. In the mean time if you alter the memory header all should be well.
Ant. I'm hard, yet soft.
I'm coloured, yet clear.
I'm fruity and sweet.
I'm jelly, what am I? Muse on it further, I shall return! - David Walliams (Little Britain) -
it's quite easy to reproduce. #include #include class A { int i; public: A() : i(1) {} virtual ~A() { std::cout << "in ~A()\n"; } }; std::auto_ptr bad_function() { return new A(); } int main() { std::auto_ptr bug = bad_function(); bug.reset(); return 0; } the thing is although auto_ptr(pointer_type) is explicit, vc8 compiler somehow finds a way to cast A* to auto_ptr. what's even worse is that it's doing this by dereferencing pointer before assinging to auto_ptr::_Myptr. in situation when object has virtual functions this makes vitrual functions table pointer __vfptr to contain a pointer to the first virtual function of the class (A::'scalar deleting destrustor' in this example) instead of A::vftable. so when you call any virtual fuction (virtual destructor in this case) control goes to a random address and you get 'Access violation'. in my case things were worse since auto_ptr was a global variable and program crashed on exit so it was quite hard to detect when things started to go wrong. of course any(?) other compiler will easily spot the problem. 'return new A()' must be 'return std::auto_ptr(new A())' instead. i just wonder why vc8 behaves this way... ps. yes, i used google and hadn't found anything helpful. pss. yes, i have SP1 installed and i don't use any STL replacements. Constantin Bryzgalin http://www.oneclicktools.com