Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can print stack trace in catch? #346

Open
K-KaUI opened this issue Jan 9, 2025 · 4 comments
Open

Can print stack trace in catch? #346

K-KaUI opened this issue Jan 9, 2025 · 4 comments

Comments

@K-KaUI
Copy link

K-KaUI commented Jan 9, 2025

Hi,
In a try block, several functions are called (which may come from third-party libraries). To ensure the system runs properly, exceptions thrown by these functions need to be caught. When an exception is caught, the call stack should be printed to help with troubleshooting, just like in the following Python example.
I understand that due to the stack unwinding issue in the C++ exception mechanism, it seems difficult to implement something similar to Python or other languages where the exception stack is printed in the catch block. Does backward-cpp support this feature? Or is there another way to achieve this?

import traceback

def do_something():
    raise Exception("throw exception from third-party library")

def test1():
    print("test1 ok")

def test2():
    do_something()

def test3():
    print("test3 ok")

if __name__ == '__main__':
    try:
        test1()
        test2()
        test3()
    except Exception as e:
        print(e)
        traceback.print_exc()
    print("do something else")
 
python test_exception.py 
test1 ok
throw exception from third-party library
Traceback (most recent call last):
  File "test_exception.py", line 18, in <module>
    test2()
  File "test_exception.py", line 10, in test2
    do_something()
  File "test_exception.py", line 4, in do_something
    raise Exception("throw exception from third-party library")
Exception: throw exception from third-party library
do something else

When using backward-cpp without exception handling, the program crashes and correctly prints the stack trace. However, when an exception is caught, it does nothing and does not print the stack trace.

#define BACKWARD_HAS_BFD 1
#include <iostream>
#include <exception>
#include <stdexcept>
#include "backward.hpp"
backward::SignalHandling sh{};
void do_something() {
    throw std::runtime_error("throw exception from third-party library");
}
void test1() {
    std::cout << "test1 ok" << std::endl;
}
void test2() {
    do_something();
}
void test3() {
    std::cout << "test3 ok" << std::endl;
}
int main() {
    // try {
        test1();
        test2();
        test3();
    // } catch (const std::exception& e) {
    //     std::cout << e.what() << std::endl;
    //     std::cout << "Exception caught: " << e.what() << std::endl;
    // }
    std::cout << "do something else" << std::endl;
    return 0;
}

./test_exception
test1 ok
terminate called after throwing an instance of 'std::runtime_error'
  what():  throw exception from third-party library
Stack trace (most recent call last):
#10   Object "", at 0xffffffffffffffff, in 
#9    Object "build/test_exception", at 0x55e45ba55fcd, in _start
BFD: DWARF error: section .debug_info is larger than its filesize! (0x93f189 vs 0x531098)
#8    Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7f40ba673082, in __libc_start_main
#7  | Source "test/test_exception.cpp", line 22, in main
    |    20:     // try {
    |    21:         test1();
    | >  22:         test2();
    |    23:         test3();
    |    24:     // } catch (const std::exception& e) {
      Source "test/test_exception.cpp", line 14, in test2() [0x55e45ba55e1d]
         11:     std::cout << "test1 ok" << std::endl;
         12: }
         13: void test2() {
      >  14:     do_something();
         15: }
         16: void test3() {
         17:     std::cout << "test3 ok" << std::endl;
#6    Source "test/test_exception.cpp", line 8, in do_something() [0x55e45ba560e7]
          5: #include "backward.hpp"
          6: backward::SignalHandling sh{};
          7: void do_something() {
      >   8:     throw std::runtime_error("throw exception from third-party library");
          9: }
         10: void test1() {
         11:     std::cout << "test1 ok" << std::endl;
#5    Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa55698, in __cxa_throw
#4    Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa553e6, in std::terminate()
#3    Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa5537b, in std::rethrow_exception(std::__exception_ptr::exception_ptr)
#2    Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa498d0, in __cxa_throw_bad_array_new_length
#1    Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7f40ba671858, in abort
#0    Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7f40ba69200b, in gsignal
Aborted (Signal sent by tkill() 168610 1000)
Aborted (core dumped)
#define BACKWARD_HAS_BFD 1
#include <iostream>
#include <exception>
#include <stdexcept>
#include "backward.hpp"
backward::SignalHandling sh{};
void do_something() {
    throw std::runtime_error("throw exception from third-party library");
}
void test1() {
    std::cout << "test1 ok" << std::endl;
}
void test2() {
    do_something();
}
void test3() {
    std::cout << "test3 ok" << std::endl;
}
int main() {
    try {
        test1();
        test2();
        test3();
    } catch (const std::exception& e) {
        std::cout << e.what() << std::endl;
        std::cout << "Exception caught: " << e.what() << std::endl;
    }
    std::cout << "do something else" << std::endl;
    return 0;
}

./test_exception
test1 ok
throw exception from third-party library
Exception caught: throw exception from third-party library
do something else
@bombela
Copy link
Owner

bombela commented Jan 9, 2025 via email

@K-KaUI
Copy link
Author

K-KaUI commented Jan 9, 2025

You would have to collect the function pointer/stack trace at the location where the error is produced (in do_something). Then you can print it within the catch handler.

On Thu, Jan 9, 2025, 10:58 K-KaUI @.> wrote: In a try block, several functions are called (which may come from third-party libraries). To ensure the system runs properly, exceptions thrown by these functions need to be caught. When an exception is caught, the call stack should be printed to help with troubleshooting, just like in the following Python example. I understand that due to the stack unwinding issue in the C++ exception mechanism, it seems difficult to implement something similar to Python or other languages where the exception stack is printed in the catch block. Does backward-cpp support this feature? Or is there another way to achieve this? import traceback def do_something(): raise Exception("throw exception from third-party library") def test1(): print("test1 ok") def test2(): do_something() def test3(): print("test3 ok") if name == 'main': try: test1() test2() test3() except Exception as e: print(e) traceback.print_exc() print("do something else") python test_exception.py test1 okthrow exception from third-party libraryTraceback (most recent call last): File "test_exception.py", line 18, in test2() File "test_exception.py", line 10, in test2 do_something() File "test_exception.py", line 4, in do_something raise Exception("throw exception from third-party library")Exception: throw exception from third-party librarydo something else When using backward-cpp without exception handling, the program crashes and correctly prints the stack trace. However, when an exception is caught, it does nothing and does not print the stack trace. #define BACKWARD_HAS_BFD 1 #include #include #include #include "backward.hpp" backward::SignalHandling sh{};void do_something() { throw std::runtime_error("throw exception from third-party library"); }void test1() { std::cout << "test1 ok" << std::endl; }void test2() { do_something(); }void test3() { std::cout << "test3 ok" << std::endl; }int main() { // try { test1(); test2(); test3(); // } catch (const std::exception& e) { // std::cout << e.what() << std::endl; // std::cout << "Exception caught: " << e.what() << std::endl; // } std::cout << "do something else" << std::endl; return 0; } ./test_exception test1 ok terminate called after throwing an instance of 'std::runtime_error' what(): throw exception from third-party library Stack trace (most recent call last): #10 Object "", at 0xffffffffffffffff, in #9 Object "build/test_exception", at 0x55e45ba55fcd, in _start BFD: DWARF error: section .debug_info is larger than its filesize! (0x93f189 vs 0x531098) #8 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7f40ba673082, in __libc_start_main #7 | Source "test/test_exception.cpp", line 22, in main | 20: // try { | 21: test1(); | > 22: test2(); | 23: test3(); | 24: // } catch (const std::exception& e) { Source "test/test_exception.cpp", line 14, in test2() [0x55e45ba55e1d] 11: std::cout << "test1 ok" << std::endl; 12: } 13: void test2() { > 14: do_something(); 15: } 16: void test3() { 17: std::cout << "test3 ok" << std::endl; #6 Source "test/test_exception.cpp", line 8, in do_something() [0x55e45ba560e7] 5: #include "backward.hpp" 6: backward::SignalHandling sh{}; 7: void do_something() { > 8: throw std::runtime_error("throw exception from third-party library"); 9: } 10: void test1() { 11: std::cout << "test1 ok" << std::endl; #5 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa55698, in __cxa_throw #4 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa553e6, in std::terminate() #3 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa5537b, in std::rethrow_exception(std::__exception_ptr::exception_ptr) #2 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa498d0, in __cxa_throw_bad_array_new_length #1 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7f40ba671858, in abort #0 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7f40ba69200b, in gsignalAborted (Signal sent by tkill() 168610 1000)Aborted (core dumped) #define BACKWARD_HAS_BFD 1 #include #include #include #include "backward.hpp" backward::SignalHandling sh{};void do_something() { throw std::runtime_error("throw exception from third-party library"); }void test1() { std::cout << "test1 ok" << std::endl; }void test2() { do_something(); }void test3() { std::cout << "test3 ok" << std::endl; }int main() { try { test1(); test2(); test3(); } catch (const std::exception& e) { std::cout << e.what() << std::endl; std::cout << "Exception caught: " << e.what() << std::endl; } std::cout << "do something else" << std::endl; return 0; } ./test_exception test1 okthrow exception from third-party library Exception caught: throw exception from third-party librarydo something else — Reply to this email directly, view it on GitHub <#346>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABUZDFZQO4DGAHKPMG3YJT2JZB3BAVCNFSM6AAAAABU3YPVBGVHI2DSMVQWIX3LMV43ASLTON2WKOZSG43TOMZWGE2TKNQ . You are receiving this because you are subscribed to this thread.Message ID: @.>

Thank you for your reply. do_something simulates an exception thrown by a third-party library, and I don't have the ability to collect function pointers/stack trace within it.

@bombela
Copy link
Owner

bombela commented Jan 9, 2025 via email

@K-KaUI
Copy link
Author

K-KaUI commented Jan 10, 2025

I don't think C++ embed the source (code pointer) of exceptions. C++ walks the stack up to find a catch handler. If it doesn't find any, then it ultimately raises a signal, with the source (code pointer) of the exception. Hence why you can print it in your test. But when a catch handler is found, I don't think this code pointer is kept around. I do recall C++11 (or 17?) added some functions to manipulate exceptions (for example to capture and re throw across threads etc). I wonder if there is something there to explore.

On Thu, Jan 9, 2025, 11:38 K-KaUI @.> wrote: You would have to collect the function pointer/stack trace at the location where the error is produced (in do_something). Then you can print it within the catch handler. … <#m_-6938620540204400117_> On Thu, Jan 9, 2025, 10:58 K-KaUI @.> wrote: In a try block, several functions are called (which may come from third-party libraries). To ensure the system runs properly, exceptions thrown by these functions need to be caught. When an exception is caught, the call stack should be printed to help with troubleshooting, just like in the following Python example. I understand that due to the stack unwinding issue in the C++ exception mechanism, it seems difficult to implement something similar to Python or other languages where the exception stack is printed in the catch block. Does backward-cpp support this feature? Or is there another way to achieve this? import traceback def do_something(): raise Exception("throw exception from third-party library") def test1(): print("test1 ok") def test2(): do_something() def test3(): print("test3 ok") if name == 'main': try: test1() test2() test3() except Exception as e: print(e) traceback.print_exc() print("do something else") python test_exception.py test1 okthrow exception from third-party libraryTraceback (most recent call last): File "test_exception.py", line 18, in test2() File "test_exception.py", line 10, in test2 do_something() File "test_exception.py", line 4, in do_something raise Exception("throw exception from third-party library")Exception: throw exception from third-party librarydo something else When using backward-cpp without exception handling, the program crashes and correctly prints the stack trace. However, when an exception is caught, it does nothing and does not print the stack trace. #define BACKWARD_HAS_BFD 1 #include #include #include #include "backward.hpp" backward::SignalHandling sh{};void do_something() { throw std::runtime_error("throw exception from third-party library"); }void test1() { std::cout << "test1 ok" << std::endl; }void test2() { do_something(); }void test3() { std::cout << "test3 ok" << std::endl; }int main() { // try { test1(); test2(); test3(); // } catch (const std::exception& e) { // std::cout << e.what() << std::endl; // std::cout << "Exception caught: " << e.what() << std::endl; // } std::cout << "do something else" << std::endl; return 0; } ./test_exception test1 ok terminate called after throwing an instance of 'std::runtime_error' what(): throw exception from third-party library Stack trace (most recent call last): #10 <#10> Object "", at 0xffffffffffffffff, in #9 <#9> Object "build/test_exception", at 0x55e45ba55fcd, in _start BFD: DWARF error: section .debug_info is larger than its filesize! (0x93f189 vs 0x531098) #8 <#8> Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7f40ba673082, in __libc_start_main #7 <#7> | Source "test/test_exception.cpp", line 22, in main | 20: // try { | 21: test1(); | > 22: test2(); | 23: test3(); | 24: // } catch (const std::exception& e) { Source "test/test_exception.cpp", line 14, in test2() [0x55e45ba55e1d] 11: std::cout << "test1 ok" << std::endl; 12: } 13: void test2() { > 14: do_something(); 15: } 16: void test3() { 17: std::cout << "test3 ok" << std::endl; #6 <#6> Source "test/test_exception.cpp", line 8, in do_something() [0x55e45ba560e7] 5: #include "backward.hpp" 6: backward::SignalHandling sh{}; 7: void do_something() { > 8: throw std::runtime_error("throw exception from third-party library"); 9: } 10: void test1() { 11: std::cout << "test1 ok" << std::endl; #5 <#5> Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa55698, in __cxa_throw #4 <#4> Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa553e6, in std::terminate() #3 <#3> Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa5537b, in std::rethrow_exception(std::__exception_ptr::exception_ptr) #2 <#2> Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7f40baa498d0, in __cxa_throw_bad_array_new_length #1 <#1> Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7f40ba671858, in abort #0 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7f40ba69200b, in gsignalAborted (Signal sent by tkill() 168610 1000)Aborted (core dumped) #define BACKWARD_HAS_BFD 1 #include #include #include #include "backward.hpp" backward::SignalHandling sh{};void do_something() { throw std::runtime_error("throw exception from third-party library"); }void test1() { std::cout << "test1 ok" << std::endl; }void test2() { do_something(); }void test3() { std::cout << "test3 ok" << std::endl; }int main() { try { test1(); test2(); test3(); } catch (const std::exception& e) { std::cout << e.what() << std::endl; std::cout << "Exception caught: " << e.what() << std::endl; } std::cout << "do something else" << std::endl; return 0; } ./test_exception test1 okthrow exception from third-party library Exception caught: throw exception from third-party librarydo something else — Reply to this email directly, view it on GitHub <#346 <#346>>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABUZDFZQO4DGAHKPMG3YJT2JZB3BAVCNFSM6AAAAABU3YPVBGVHI2DSMVQWIX3LMV43ASLTON2WKOZSG43TOMZWGE2TKNQ https://github.com/notifications/unsubscribe-auth/AABUZDFZQO4DGAHKPMG3YJT2JZB3BAVCNFSM6AAAAABU3YPVBGVHI2DSMVQWIX3LMV43ASLTON2WKOZSG43TOMZWGE2TKNQ . You are receiving this because you are subscribed to this thread.Message ID: @.> Thank you for your reply. do_something simulates an exception thrown by a third-party library, and I don't have the ability to collect function pointers/stack trace within it. — Reply to this email directly, view it on GitHub <#346 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABUZDDYEYITQU44HMN4WM32JZGTPAVCNFSM6AAAAABU3YPVBGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNZZG44DGOBQG4 . You are receiving this because you commented.Message ID: @.**>

Thanks, I'll keep exploring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants