This question provides more clarity on the problem described here. I did some more investigation and found that the stack unwinding is not happening in the following piece of code:
class One
{
public:
int x ;
};
class Wrapper
{
public:
Wrapper(CString csText):mcsText(csText)
{
CString csTempText;
csTempText.Format("Wrapper constructor :: %s\n", mcsText);
OutputDebugString(csTempText);
}
~Wrapper()
{
CString csTempText;
csTempText.Format("Wrapper destructor :: %s\n", mcsText);
OutputDebugString(csTempText);
}
CString mcsText;
};
class Test
{
public:
void notifyError()
{
try
{
int x = 10;
}
catch(...) {}
}
void OnRecvBuffer()
{
try
{
Wrapper a("AddRef");
One* p = NULL;
p->x = 10;
}
catch(...)
{
notifyError();
}
}
};
int main()
{
Test* pTest = new Test;
pTest->OnRecvBuffer();
OutputDebugString("Test");
}
I compiled this code using VC6 SP5 compiler and the output is "Wrapper constructor :: AddRef!!!" (i.e. the destructor of wrapper object which was constructed on stack is not called. Is this the expected behavior ? or is it a bug with VC compiler ? Can I use some compiler flags so that the stack unwinding happens in this case?
The C++ standard does not give anything to work with in case of Undefined Behavior. Even if MS does. That's a platform specific thing -- so beware. Some such floating point exceptions are turned to Win32 exceptions which you can attempt to catch with _set_se_translator(). The problem is you can catch Win32 exceptions but then your stack will not be unwound properly. At least that is not something you can bet your life on. Wherein lies the futility of the exercise.
Update: The exception is thrown intentionally to check the stack unwinding. The question is why Wrapper class's destructor is not getting called. – Naveen
If this is the case -- don't do it. There are better ways to throw exceptions than via Undefined Behavior.
E.g:
void OnRecvBuffer()
{
try
{
Wrapper a("AddRef");
throw 42; // this'll throw an exception without invoking UB
}
catch(...)
{
notifyError();
}
}
You cannot dereference a NULL pointer. You are invoking Undefined Behavior here:
One* p = NULL;
p->x = 10;
After that line all bets are off and you could have killed us all ;)
p is a pointer to a One object. It should contain the address of an One object. You have initialized it to 0 -- there is no object at address 0. 0 is not a valid address for any object (this is guranteed by the standard).
If you want to use SEH, you must use _set_se_translator function and /EHa compiler option.
Because C++ regular exception does not handle this kind of exception, you have to use SEH which does not know anything about the app and does not unwind.
This is undefined behavior:
One* p = NULL;
p->x = 10;
At this point the application is free to crash without unwinding the stack.
If you want to test the stack unwinding replace this with:
throw 42; // Life the Universe and Everything thrown away
You should not dynamically allocate all your objcts this is C++ not Java!
int main()
{
Test pTest; // Note the lack of new!
pTest.OnRecvBuffer();
OutputDebugString("Test");
}
Related
I need to hook into C++'s exception throwing mechanism like this:
namespace __cxxabiv1
{
extern "C" void __cxa_throw(void* voidPointerToActualObject, std::type_info* stdTypeInfoOfActualObject, void (*destructor)(void *))
{
// If thrownException is a custom exception type or something deriving from it, poke a value into it.
}
}
If you're wondering "Why would you do that?"
I have this simple example of throwing an exception that's part of a very simple class hierarchy:
#include <stdexcept>
class Upper : public std::exception
{
public:
int pokeMe = 111111;
};
class Lower : public Upper {};
int main()
{
throw Lower();
}
#include <cxxabi.h>
namespace __cxxabiv1
{
extern "C" void __cxa_throw(void* voidPointerToActualObject, std::type_info* stdTypeInfoOfActualObject, void (*destructor)(void *))
{
// The point is to do the equivalent of this:
Lower* staticallyTypedPointerToActualObject = reinterpret_cast<Lower*>(voidPointerToActualObject);
auto thisWorks = dynamic_cast<Upper*>(staticallyTypedPointerToActualObject);
thisWorks->pokeMe = 222222;
// But we don't know the actual static type, so we can't get a statically typed pointer. We only have a void* and a type_info:
auto abiTypeInfoOfActualObject = dynamic_cast<const abi::__class_type_info*>(stdTypeInfoOfActualObject);
auto abiTypeInfoOfUpper = dynamic_cast<const abi::__class_type_info*>(&typeid(Upper));
Upper* thisDoesNotWork = reinterpret_cast<Upper*>(abi::__dynamic_cast(voidPointerToActualObject, abiTypeInfoOfActualObject, abiTypeInfoOfUpper, -1));
thisDoesNotWork->pokeMe = 333333;
// Elided for clarity: Call the original __cxa_throw function here
// Instead, suppress these warnings:
(void)destructor; // Unused parameter
while (1) { } // Return from non-returning function
}
}
I don't see a reason why __dynamic_cast shouldn't be able to upcast, but it returns nullptr.
Why? And how do I get it to work?
It seems to be able to do downcasts just fine, BTW:
auto abiTypeInfoOfActualObject = dynamic_cast<const abi::__class_type_info*>(&typeid(Upper)); // Plonking this here for testing
auto abiTypeInfoOfUpper = dynamic_cast<const abi::__class_type_info*>(&typeid(Lower)); // Casting to Lower instead of Upper
Lower* thisDoesNotWork = reinterpret_cast<Lower*>(abi::__dynamic_cast(voidPointerToActualObject, abiTypeInfoOfActualObject, abiTypeInfoOfUpper, -1));
I managed to dig up this archived conversation from 2004:
The ABI document does not require that __dynamic_cast perform a
derived-to-base cast. Those __dynamic_cast operations that can
actually be performed statically by the compiler must be performed
statically by the compiler -- the runtime library does not expect to
be called in that situation.
So that answers that question. Greeeeeeat.
But the conversation luckily mentions:
Yes; the holder knows the static type; it can throw a pointer of that
type. The cast operation can catch the pointer type it's looking for,
or fail the cast with catch(...).
That gave me the idea to try this (simplified version):
namespace __cxxabiv1
{
using ThrowFunction = decltype(__cxa_throw)*;
ThrowFunction oldThrowFunction = nullptr;
extern "C" void __cxa_throw(void* voidPointerToActualObject, std::type_info* stdTypeInfoOfActualObject, void (*destructor)(void *))
{
if (oldThrowFunction == nullptr)
{
oldThrowFunction = (ThrowFunction)dlsym(RTLD_NEXT, "__cxa_throw");
}
try
{
oldThrowFunction(voidPointerToActualObject, stdTypeInfoOfActualObject, destructor);
}
catch (Upper& ex)
{
ex.pokeMe = 333333;
}
catch (...)
{
}
oldThrowFunction(voidPointerToActualObject, stdTypeInfoOfActualObject, destructor);
}
}
And I can't believe it but it actually works!
Edit: Disclaimer: It seems that this way, the destructor callback is actually called twice, because if use std::string pokeMe, the string is trashed by the time I get to the second call to oldThrowFunction. I'll experiment around with over the next few days.
Edit2: That's indeed the case. I couldn't find anything indicating whether __cxa_throw accepts nullptr as the destructor argument (it didn't crash for me, at least), so the safest bet is to pass a pointer to an empty dummy function:
void dummyDestructor(void*)
{
}
//...
oldThrowFunction(voidPointerToActualObject, stdTypeInfoOfActualObject, &dummyDestructor);
Edit 3: Goddamnit! It seems that this causes memory corruption. malloc crashes with a segfault at a later point when doing this.
Back to square -5.
I wrote sample code that should cause access violation, but it does not.
I think the exception should occur in GetSession1(), GetSession2() function for return *m_pObj, but it does not. Why is that?
Header file
class CSession
{
public:
CSession() {};
~CSession() {};
CSession(const CSession& rhs) {};
private:
long m_lUSN;
};
class CTest
{
public:
CSession* m_pObj;
CSession& GetSesstion1() { m_pObj = NULL; return *m_pObj; }
CSession GetSesstion2(); { m_pObj = NULL; return *m_pObj; }
};
Cpp file
int _tmain(int argc, _TCHAR* argv[])
{
CTest test;
CSession Session2 = test.GetSesstion1();
CSession Session3 = test.GetSesstion2();
return 0;
};
Dereferencing a null pointer is undefined behaviour (a more "serious" link here: Why dereferencing a null pointer is undefined behaviour?). Your program may crash, or may do whatever it wants. The C++ standard doesn't mandate to have an "access violation".
Undefined behaviour (UB) is bad, and you cannot rely on a compiler to always catch it. For example, the code below makes it clear why UB is bad:
#include <iostream>
int main()
{
int *p = nullptr;
int q = *p;
//std::cout << q;
}
On my machine, I get no warning whatsoever, the code compiles and runs just fine. If I un-comment the std::cout line, BANG, it crashes. That's because probably the compiler optimized out the dereferencing of the null pointer, however cannot optimize it out when trying to use q. That's what's probably happening in your code, but again, it is UB and the fact that the program runs should not give you any reassurance.
You wrote constructors that do not do anything, so you are not actually trying to access m_lUSN when located at a NULL address, thus you don't get any AVs. If you change your CSession() copy constructor to copy the value of rhs.m_lUSN to this->m_lUSN, or add public getter/setter methods so _tmain() can read/set the m_lUSN value, you will start seeing AVs occur from the objects returned by GetSesstion(1|2)().
I have the following code:
class ClassA
{
public:
ClassA(std::string str);
std::string GetSomething();
};
int main()
{
std::string s = "";
try
{
ClassA a = ClassA(s);
}
catch(...)
{
//Do something
exit(1);
}
std::string result = a.GetSomething();
//Some large amount of code using 'a' out there.
}
I would like the last line could access the a variable. How could I achieve that, given ClassA doesn't have default constructor ClassA() and I would not like to use pointers? Is the only way to add a default constructor to ClassA?
You can't or shouldn't. Instead you could just use it within the try block, something like:
try
{
ClassA a = ClassA(s);
std::string result = a.GetSomething();
}
catch(...)
{
//Do something
exit(1);
}
The reason is that since a goes out of scope after the try block referring to the object after that is undefined behavior (if you have a pointer to where it were).
If you're concerned with a.GetSomething or the assignment throws you could put a try-catch around that:
try
{
ClassA a = ClassA(s);
try {
std::string result = a.GetSomething();
}
catch(...) {
// handle exceptions not from the constructor
}
}
catch(...)
{
//Do something only for exception from the constructor
exit(1);
}
You can use some sort of optional or just use std::unique_ptr.
int main()
{
std::string s = "";
std::unique_ptr<ClassA> pa;
try
{
pa.reset(new ClassA(s));
}
catch
{
//Do something
exit(1);
}
ClassA& a = *pa; // safe because of the exit(1) in catch() block
std::string result = a.GetSomething();
//Some large amount of code using 'a' out there.
}
Of course, just extending the try block to include the usage of a is the simplest solution.
Also, if you were really planning to exit(1) or otherwise abort the program on failure then simply don't put a try block here at all. The exception will propagate up, aborting the program if it is not caught .
One alternative is to use std::optional . This is the same sort of concept as using a pointer, but it uses automatic allocation and so you are less likely to create a memory leak. This is currently experimental status; you can use boost::optional instead if your compiler doesn't have std::experimental::optional:
#include <experimental/optional>
using std::experimental::optional;
using std::experimental::in_place;
// ...
optional<ClassA> a;
try
{
a = optional<ClassA>(in_place, s);
}
catch(...)
{
// display message or something
}
std::string result;
if ( a )
result = a->GetSomething();
I'd like to reiterate though that this is a bit of a spaghetti style and it'd be better to design your code differently so you aren't continually testing whether construction succeeded or failed.
This requires ClassA be movable or copyable. The in_place is a special argument which invokes a perfect forwarding constructor for the remaining arguments. Without in_place you can only give an actual ClassA as constructor argument, it doesn't consider implicit conversions to ClassA. (This is how optional avoids the ambiguity between copy-construction and list-initialization from object of the same type).
Suppose we have some class (call it classs) with the default constructor which can throw some exception. I need to use the object of that class in a function as follows:
try{
classs c;
} catch(bad_init& b){
//log
}
//if the class initialized succesfully
//do some with c
But c is declared in the try's block scope and therefore is not visible in the function scope. How can I do that?
I don't want to wrap the whole function's body because there're some code throwing another kind of exception.
You cannot do this directly. As long as c is in scope, code has the right to assume if contains an alive object of type classs. If the constructor throws an exception, c will not be initialised and that cannot hold.
The correct way to do this is to wrap the entire scope of c in the try block. After all, code which uses c cannot do anything meaningful if c failed to initialise. If some other code later in that block can throw other exceptions and you don't want to catch them, just don't—let them propagate up the stack normally.
If you cannot use this approach is for some reason, you can resort to something like boost::optional and delayed init:
boost::optional<classs> c;
try {
c = classs();
} catch (bad_init&) {
}
Or do something similar manually with std::aligned_storage, placement new and a conditional destructor call.
a workaround is to use std::unique_ptr:
std::unique_ptr<A> a;
try{
a = std::make_unique<A>();
} catch(bad_init& b){
//log
}
if (a){
//do
}
I would simply catch the exception at the level of the caller. No need to make things complicated.
void functionThatThrows()
{
classs c;
// do something with c
}
void callerThatCatches()
{
try {
functionThatThrows();
} catch(...) {
// handle exception
}
}
The simplest way is just to extend the try block until you no longer need your object :
try{
classs c;
//if the class initialized succesfully
//do some with c
} catch(bad_init& b){
//log
}
For the below C++ code, I am getting an compiler error:
class Mkt
{
int k;
public:
Mkt(int n): k(n)
{
throw;
}
~Mkt()
{
cout<<"\n\nINSIDE Mkt DTOR function:\t"<<endl;
}
void func1()
{
cout<<"\n\nINSIDE FUNC1 function....value of k is:\t"<<k<<endl;
}
};
int main(int argc, char* argv[] )
{
try
{
std::auto_ptr<Mkt> obj(new Mkt(10)); //no implicit conversion
obj.func1(); //error C2039: 'func1' : is not a member of 'std::auto_ptr<_Ty>'
}
catch(...)
{
cout<<"\n\nINSIDE EXCEPTION HANDLER..........."<<endl;
}
return 0;
}
I am not able to understand why I am getting the error C2039? I am using VS 2008 compiler.
Pls help.
Thanks
It is auto_ptr, this means, that it is pointer :). You must use operator->:
obj->func1();
You have to use ->
obj->func1();
auto_ptr doesn't have func1(), but it has operator ->() that will yield a Mkt* pointer stored inside and then -> will be used again on that pointer and this will call the Mkt::func1() member function.
Be aware that after you fix the compilation problem (change dot-operator into -> operator) you will encounter a huge run-time problem.
Mkt(int n): k(n)
{
throw;
}
throw without an argument is meant to be used inside catch-blocks and causes re-throwing handled exception. Called outside catch-blocks will result in a call to abort function and your program termination.
You probably meant something like
throw std::exception();
or, better,
throw AnExceptionDefinedByYou();
This is very basic thing in c++ .. auto_ptr - the "ptr" stands for "pointer",