Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
812 views
in Technique[技术] by (71.8m points)

macos - `gdb` unable to unwind a stack

Consider following (broken) code:

#include <iostream>
#include <memory>

using namespace std;

class Test {
    public:
        unique_ptr<string> s;

        Test() : s(NULL) {
        }

        void update(string& st) {
            s = unique_ptr<string>(&(st));
        }
};


void update(Test& t) {
    string s("Hello to you");
    t.update(s);
}

int main() {
    Test t;
    update(t);
    cout << *t.s << endl;
}

Here we have error in method Test::update() we do not make a uniq copy of an object. So when the program is run under macOS, you'll get:

$ ./test
Hello t??E]?
test(44981,0x7fff99ba93c0) malloc: *** error for object 0x7fff5d45b690: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
[1]    44981 abort      ./test

I've been able to to debug this case successfully using lldb. Even without setting a breakpoint in malloc_error_break, just running application until it gets caught in SIGABRT handler.

lldb ./test

(lldb) target create "./test"
Current executable set to './test' (x86_64).

(lldb) run
Process 44993 launched: './test' (x86_64)
Hello t??_?
test(44993,0x7fff99ba93c0) malloc: *** error for object 0x7fff5fbff680: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Process 44993 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff90d6cd42 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
->  0x7fff90d6cd42 <+10>: jae    0x7fff90d6cd4c            ; <+20>
    0x7fff90d6cd44 <+12>: movq   %rax, %rdi
    0x7fff90d6cd47 <+15>: jmp    0x7fff90d65caf            ; cerror_nocancel
    0x7fff90d6cd4c <+20>: retq
Target 0: (test) stopped.

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff90d6cd42 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff90e5a457 libsystem_pthread.dylib`pthread_kill + 90
    frame #2: 0x00007fff90cd2420 libsystem_c.dylib`abort + 129
    frame #3: 0x00007fff90dc1fe7 libsystem_malloc.dylib`free + 530
    frame #4: 0x0000000100001f7b test`Test::~Test() [inlined] std::__1::default_delete<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::operator(this=0x00007fff5fbff730, __ptr="ax94x99?x7f??_?x7fx80?_?x7f0?_?x7f0?_?x7f0?_?x7f0?_?x7f0?_?x7f??_?x7fx15x1ex01x80?_?x7f
0")(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*) const at memory:2397
    frame #5: 0x0000000100001f46 test`Test::~Test() [inlined] std::__1::unique_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::reset(this=0x00007fff5fbff730, __p="") at memory:2603
    frame #6: 0x0000000100001ef3 test`Test::~Test() [inlined] std::__1::unique_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::~unique_ptr(this=0x00007fff5fbff730) at memory:2571
    frame #7: 0x0000000100001ef3 test`Test::~Test() [inlined] std::__1::unique_ptr<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::default_delete<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >::~unique_ptr(this=0x00007fff5fbff730) at memory:2571
    frame #8: 0x0000000100001ef3 test`Test::~Test(this=0x00007fff5fbff730) at main.cpp:6
    frame #9: 0x0000000100001e15 test`Test::~Test(this=0x00007fff5fbff730) at main.cpp:6
    frame #10: 0x0000000100001ab6 test`main at main.cpp:28
    frame #11: 0x00007fff90c3e235 libdyld.dylib`start + 1

Now I see that the problem is in Test destructor, and from here it's a piece of cake.

Unfortunately, trying to debug this case using gdb under macOS was a total failure. Here is what I've done:

$ gdb ./test
GNU gdb (GDB) 8.0.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin16.7.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...Reading symbols from /Users/bazhenov/Developer/linear-counter/tests/test/test.dSYM/Contents/Resources/DWARF/test...done.
done.

(gdb) run
Starting program: /Users/bazhenov/Developer/linear-counter/tests/test/test
[New Thread 0x1403 of process 45204]
warning: unhandled dyld version (15)
Hello tQ?_?
test(45204,0x7fff99ba93c0) malloc: *** error for object 0x7fff5fbff650: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

Thread 2 received signal SIGABRT, Aborted.
0x00007fff90d6cd42 in ?? ()

(gdb) bt
#0  0x00007fff90d6cd42 in ?? ()
#1  0x00007fff90e5a457 in ?? ()
#2  0x00007fff5fbff590 in ?? ()
#3  0x0000030700000000 in ?? ()
#4  0x00007fff5fbff590 in ?? ()
#5  0x00007fff5fbff650 in ?? ()
#6  0x00007fff5fbff5a0 in ?? ()
#7  0x00007fff90cd2420 in ?? ()
#8  0xffffffff00000018 in ?? ()
#9  0x00007fff5fbff5b0 in ?? ()
#10 0x00007fffffffffdf in ?? ()
#11 0x00000001000c4000 in ?? ()
#12 0x00007fff5fbff5f0 in ?? ()
#13 0x00007fff90dc1fe7 in ?? ()
#14 0x378b45e65b700074 in ?? ()
#15 0x00007fff99ba00ac in ?? ()
#16 0x0000000000000000 in ?? ()
(gdb)

The question is: why gdb fails to unwind the stack correctly and what options do I have if I need to get correct backtrace using gdb?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

why gdb fails to unwind the stack correctly

There are some problems on Mac OS X Sierra with gdb, see this post and gdb bug report.

what options do I have if I need to get correct backtrace using gdb

You can try to downgrade Mac OS (don't know whether is it possible) or try to apply temporary hack patch from above bug report.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...