Stack Failure Causes

I was debugging the application and found the following code:

int Func() { try { CSingleLock aLock(&m_CriticalSection, TRUE); { //user code } } catch(...) { //exception handling } return -1; } 

m_CriticalSection is CCricialSection.

I found that the user code throws an exception, so m_CriticalSection is not issued at all. This means that for some reason the stack is corrupted, and therefore recovery failed.

My question is: 1) In what different scenarios can the unwinding of the stack fail?

2) that another exception option may be chosen, so the stack reset fails.

3) Can I solve this problem by putting CSingleLock outside the try block?

Thanks,

0
source share
4 answers

Are you getting abnormal termination of the program?

I believe that your CCriticalSection object will be released by the CSingleLock destructor. The destructor will always be called, since it is an object on the stack. When the user code is thrown, all the stacks between throw and catch in your function will be unwound.

However, there is a chance that some other object in your user code or even the CSingleLock destructor CSingleLock another exception. In this case, the m_CriticalSection object m_CriticalSection not be released properly and std::terminate is called and your program dies.

Here is an example to demonstrate. Note. I use the std::terminate handler function to notify me of the status. You can also use std::uncaught_exception to see if there are any uncaught exceptions. This one has some nice discussion and sample code.

 struct S { S() { std::cout << __FUNCTION__ << std::endl; } ~S() { throw __FUNCTION__; std::cout << __FUNCTION__ << std::endl; } }; void func() { try { S s; { throw 42; } } catch(int e) { std::cout << "Exception: " << e << std::endl; } } void rip() { std::cout << " help me, O mighty Lord!\n"; // pray } int main() { std::set_terminate(rip); try { func(); } catch(char *se) { std::cout << "Exception: " << se << std::endl; } } 

Read this FAQ for clarity.

Can I solve this problem by putting CSingleLock outside the try block?

It's hard to say without looking at the stack and errors / crashes. Why don't you give it a try. It can also introduce a subtle bug, hiding the real problem.

+2
source

Let me start by saying that I don’t know what CSingleLock and CCriticalSection do.

What I know is that the exception specified in the "<code β†’ > " section should disable the stack and destroy any variables that were created in the try {} block.

In my opinion, I expect your aLock variable to be destroyed with the exception of an exception, but not m_CriticalSection. You pass the m_CriticalSection pointer to the aLock variable, but the m_CriticalSection object already exists and was created elsewhere.

0
source
  • Are you sure the life of your m_CriticalSection is longer than CSingleLock?
  • Maybe someone messed up your stack?
  • 3) Can I solve this problem by putting CSingleLock outside the try block?

    in this case, yes. But remember, this is not good for performance to put a large block in a mutex.

  • btw, catch (...) is not good practice in general. in Win32 it (catch (...)) to catch SEH exceptions is also not only a C ++ exception. perhaps you have a kernel in this function and catch it with catch (...).

0
source

My question is:
1) In what different scenarios can stack unwinding fail?

2) that another exception option may be chosen, so the stack reset fails.

  • Exception thrown from constructor of throw expression
  • The exception thrown from the destructor when the exception was thrown.
  • An exception is thrown that is never caught (implemented if it really spins the stack).
  • An exception that is not specified in the exception specification.
  • An exception thrown through C ABI.
  • An exception is thrown inside a thread that is not caught (Implementation is determined what happens)

3) Can I solve this problem by putting CSingleLock outside the try block?

No. All of the above leads to the termination of the application without further unwinding the stack.

0
source

All Articles