7

What are _Unwind_SjLj_Unregister and _Unwind_SjLj_Register? I get them as my top processor time users in my gprof report. google only returns links to people complaining about errors with these two.

heres the only part of my report that has times != 0:

Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
 33.33      0.03     0.03                             _Unwind_SjLj_Unregister
 22.22      0.05     0.02                             _Unwind_SjLj_Register
 11.11      0.06     0.01    13886     0.00     0.00  toint(std::string, int)
 11.11      0.07     0.01     4380     0.00     0.00  hexlify(std::string)
 11.11      0.08     0.01     2994     0.00     0.00  std::_Deque_iterator<unsigned char, unsigned char const&, unsigned char const*>::operator+(int) const
 11.11      0.09     0.01                             std::string::assign(char const*, unsigned int)

im running windows 7 x64, and compiling with codeblocks 10.05 gcc

edit:

after enabling functions that force the program to run 64 seconds, it now looks like:

Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls   s/call   s/call  name    
  8.45      3.49     3.49                             _Unwind_SjLj_Register
  7.36      6.53     3.04  4000006     0.00     0.00  CAST128::setkey(std::string)
  5.86      8.95     2.42                             _Unwind_SjLj_Unregister
  4.36     10.75     1.80 64000080     0.00     0.00  CAST128::F(int&, unsigned int&, unsigned int&, unsigned char&)
  3.68     12.27     1.52                             __dynamic_cast
  3.37     13.66     1.39                             std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&)
  3.25     15.00     1.34                             std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()
  2.88     16.19     1.19                             std::istreambuf_iterator<char, std::char_traits<char> > std::num_get<char, std::istreambuf_iterator<char, std::char_traits<char> > >::_M_extract_int<unsigned long long>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, std::_Ios_Iostate&, unsigned long long&) const
calccrypto
  • 8,583
  • 21
  • 68
  • 99

6 Answers6

4

I believe it is exception handling. The problems mostly come up when people try to link to a C++ library built in a different compiler.

totowtwo
  • 2,101
  • 1
  • 14
  • 21
  • is it a good thing or a bad thing that this is on top? im not experiencing any problems (i think). its just there in the report – calccrypto Jun 29 '11 at 05:25
  • 2
    Hmm. It's a bit surprising that your program is using 55% of its time on exception handlers. But let's think a bit more logically: I note that your profile has measured exactly 0.03 seconds and 0.02 seconds for those. And 0.01 seconds for everything else. It looks like the program took almost no time at all to run, and the profiler is unable to measure anything in less than 0.01 second granularity. You need a much longer run to get any meaningful info. You're basically looking at six grains of sand, two a bit bigger than the others, and trying to figure out how to clean up the beach. – mgiuca Jun 29 '11 at 05:34
  • lol. my program takes about .2 seconds to run. that might explain it – calccrypto Jun 29 '11 at 05:35
  • i changed my program to run for 64 secs, and the two exception handlers are still on top. CAST128 is now on top because its being run 100000+ times – calccrypto Jun 29 '11 at 05:39
  • Hm. I am compiled a code with MinGW, and every time my LastError was changed, so I was confused. I found in disassembly that the culprit was the `_Unwind_SjLj_Register`, which, of course, was inserted by the compiler, not me. I wonder, should this be considered as a bug of a MinGW? – Hi-Angel Aug 21 '14 at 06:22
  • saved my life! in my case, i first used perl's g++ to compile a library, then use mgwin's g++ to link, and the error came up. – Lei Yang Aug 18 '17 at 12:29
3

I can't give the best answer here, but I do know that SjLj refers to setjmp and longjmp. These are commonly used for exception handling. I think the _Unwind_SjLj_Register will be used internally by the compiler when you enter a try statement (to "register" a SjLj exception handler) and _Unwind_SjLj_Unregister will be used when you exit the try statement. Sort of guessing though.

mgiuca
  • 20,958
  • 7
  • 54
  • 70
  • i dont believe i have any `try`s in my program.**EDIT** nope. i checked. it might be hidden in some stl library – calccrypto Jun 29 '11 at 05:22
  • Maybe there are trys in some library you are calling. – mgiuca Jun 29 '11 at 05:24
  • But you're using the C++ standard library, and it has `try`s. – davmac Jun 29 '11 at 05:24
  • 2
    They're not called when you enter a `try` block, but when you create/destroy local objects with destructors that need calling if an exception is thrown. – Mike Seymour Jun 30 '11 at 17:23
  • @Mike Seymour, Ah good to know. That probably explains calccrypto's seeing them even though he isn't directly using try/catch. – mgiuca Jul 01 '11 at 00:57
1

First: it would probably be worth mentioning your compiler and platform for questions like this one.

Now: On some platforms/some configurations/some compilers, exception handling in C++ is implemented using the "setjmp" and "longjmp" functions (part of the standard C library). The _Unwind_SjLj_[Un]register methods are to do with this. Roughly speaking, when a try..catch block is entered, a handler needs to be registered, and when the block is left, the handler needs to be unregistered.

davmac
  • 20,150
  • 1
  • 40
  • 68
0

This is a quite specific case, but I encountered this error using the Rcpp package in R. Turns out the -std=c++11 flag caused the issue, and things worked just fine with -std=c++0x.

0

My Case

investigating a iOS dylib, which contain imported functions:

130  0x0003f1a4 0x0003b1a4 LOCAL  FUNC 0        imp._Unwind_SjLj_Register
131  0x0003f1b4 0x0003b1b4 LOCAL  FUNC 0        imp._Unwind_SjLj_Resume
132  0x0003f1c4 0x0003b1c4 LOCAL  FUNC 0        imp._Unwind_SjLj_Unregister

Explanation

_Unwind_SjLj_Unregister, _Unwind_SjLj_Register

  • _Unwind_SjLj_Unregister/_Unwind_SjLj_Register used to do Handle Exceptions
    • in which: SjLj=SJLJ =setjump/longjump

setjump/longjump

  • setjump/longjump is C standard library functions
    • The main feature of setjump and longjump function is to provide a way that deviates from standard call and return sequence.
      • This is mainly used to implement exception handling in C:
        • setjmp can be used like try (in languages like C++ and Java)
        • longjmp can be used like throw
          • Note that longjmp() transfers control to the point set by setjmp()

iOS here

  • ARM uses setjump/longjump based C++ exceptions
    • Other architectures use "zero cost" exceptions
  • iOS here using _Unwind_SjLj_Register() and _Unwind_SjLj_Unregister() to implements setjump-longjump based C++ exceptions
    • With SJLJ based exceptions any function that has a catch clause or needs to do any clean up when an exception propagates through it, needs to call _Unwind_SjLj_Register() at the start of the function and _Unwind_SjLj_Unregister() at the end. The register function is called with the address of a block of memory in the function's stack frame. The runtime keeps a linked list (stack) of these blocks - one per thread. The calling function also sets the personality and lsda fields of the block. ister() at the end. The register function is called with the address of a block of memory in the function's stack frame. The runtime keeps a linked list (stack) of these blocks - one per thread. The calling function also sets the personality and lsda fields of the block.

Reference

crifan
  • 12,947
  • 1
  • 71
  • 56
-1

In my experience of using gcc on Windows, you can avoid a lot of this overhead by avoiding allocation of memory or the potential for allocation of memory in your inner loops. The other answers point out that you get these calls when an exception might be thrown and cause calls to destructors. In my programs the exception that could be thrown in the most places is std::bad_alloc which you get when a memory allocation fails.

So if the potential exceptions in your program are also mostly std::bad_alloc, and you can move the allocation or the potential for an allocation out of your inner loop, then GCC won't have to deal with cleaning up after potential std::bad_alloc exceptions inside your inner loop. That should speed things up. Remember to consider that things like vector::push_back can allocate memory. Even if you call vector::reserve first to rule out reallocations, GCC might not be smart enough to realize that reallocation isn't going to happen.

I don't know what version of GCC you are using, but I believe that the newest version of GCC uses an exception handling mechanism that does not have this overhead. I could be wrong on that, though. It is certainly possible to implement an exception handling mechanism that does not require registering destructors dynamically since the destructors that need to be called can be inferred from the program counter.

Bjarke H. Roune
  • 3,667
  • 2
  • 22
  • 26