我正在用C ++构建模块以在Python中使用。我的流程分为三个步骤:将各个C ++源代码编译为对象,创建一个库,然后运行setup.py脚本来编译.pyx->。cpp->。so,同时引用我刚刚创建的库。
我知道我可以使用Cython setup.py一步完成所有事情,而这就是我过去所做的。将其拆分为多个步骤的原因是我希望C ++代码能够独立发展,在这种情况下,我将只使用Cython / python中的编译库。
因此,在没有错误的情况下,此流程工作正常。问题是我试图找到一个segfault的来源,所以我想获取调试符号,以便可以与gdb一起运行(我将其安装在OSX 10.14上,虽然很痛苦,但确实可行)。>
我有一个生成文件,该文件执行以下操作。
所有文件都使用最低限度的标志进行编译,但是存在-g:
gcc -mmacosx-version-min=10.7 -stdlib=libc++ -std=c++14 -c -g -O0 -I ./csrc -o /Users/colinww/system-model/build/data_buffer.o csrc/data_buffer.cpp
我认为即使在这里也有问题:当我执行nm -pa data_buffer.o时,没有看到调试符号。此外,我得到:
(base) cmac-2:system-model colinww$ dsymutil build/data_buffer.o
warning: no debug symbols in executable (-arch x86_64)
makefile有一行
cd $(CSRC_DIR) && CC=$(CC) CXX=$(CXX) python3 setup_csrc.py build_ext --build-lib $(BUILD)
setup.py的相关部分是
....
....
....
compile_args = ['-stdlib=libc++', '-std=c++14', '-O0', '-g']
link_args = ['-stdlib=libc++', '-g']
....
....
....
Extension("circbuf",
["circbuf.pyx"],
language="c++",
libraries=["cpysim"],
include_dirs = ['../build'],
library_dirs=['../build'],
extra_compile_args=compile_args,
extra_link_args=link_args),
....
....
....
ext = cythonize(extensions,
gdb_debug=True,
compiler_directives={'language_level': '3'})
setup(ext_modules=ext,
cmdclass={'build_ext': build_ext},
include_dirs=[np.get_include()])
运行此命令时,它会生成一堆编译/链接命令,例如
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/colinww/anaconda3/include -arch x86_64 -I/Users/colinww/anaconda3/include -arch x86_64 -I. -I../build -I/Users/colinww/anaconda3/lib/python3.7/site-packages/numpy/core/include -I/Users/colinww/anaconda3/include/python3.7m -c circbuf.cpp -o build/temp.macosx-10.7-x86_64-3.7/circbuf.o -stdlib=libc++ -std=c++14 -O0 -g
和
g++ -bundle -undefined dynamic_lookup -L/Users/colinww/anaconda3/lib -arch x86_64 -L/Users/colinww/anaconda3/lib -arch x86_64 -arch x86_64 build/temp.macosx-10.7-x86_64-3.7/circbuf.o -L../build -lcpysim -o /Users/colinww/system-model/build/circbuf.cpython-37m-darwin.so -stdlib=libc++ -g
在两个命令中,都存在-g标志。
最后,我用gdb运行程序
(base) cmac-2:sim colinww$ gdb python3
(gdb) run system_sim.py
它倾倒了大量与系统文件相关的内容(似乎不相关),并最终在程序出现段错误时运行我的程序:
Thread 2 received signal SIGSEGV, Segmentation fault.
0x0000000a4585469e in cpysim::DataBuffer<double>::Write(long, long, double) () from /Users/colinww/system-model/build/circbuf.cpython-37m-darwin.so
(gdb) info local
No symbol table info available.
(gdb) where
#0 0x0000000a4585469e in cpysim::DataBuffer<double>::Write(long, long, double) () from /Users/colinww/system-model/build/circbuf.cpython-37m-darwin.so
#1 0x0000000a458d6276 in cpysim::ChannelFilter::Filter(long, long, long) () from /Users/colinww/system-model/build/chfilt.cpython-37m-darwin.so
#2 0x0000000a458b0d29 in __pyx_pf_6chfilt_6ChFilt_4filter(__pyx_obj_6chfilt_ChFilt*, long, long, long) () from /Users/colinww/system-model/build/chfilt.cpython-37m-darwin.so
#3 0x0000000a458b0144 in __pyx_pw_6chfilt_6ChFilt_5filter(_object*, _object*, _object*) () from /Users/colinww/system-model/build/chfilt.cpython-37m-darwin.so
#4 0x000000010002f1b8 in _PyMethodDef_RawFastCallKeywords ()
#5 0x000000010003be64 in _PyMethodDescr_FastCallKeywords ()
如上所述,我认为问题始于初始编译步骤。这与cython无关,我只是从命令行通过-g标志调用gcc。
(base) cmac-2:system-model colinww$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
感谢您的帮助,谢谢!
我删除了gcc标签并将其更改为clang。因此,我想我现在很困惑,如果Apple将gcc别名为clang,并不表示在“那种模式”下它的行为应类似于gcc(并且暗示有人确定是这样)。
因此,我永远无法使调试符号出现在调试器中,而不得不诉诸许多有趣的if-printf语句,但是问题是由于索引变量变得不确定。因此,感谢所有建议,但问题或多或少得到了解决(直到下一次)。谢谢!
答案 0 :(得分:3)
macOS链接器不会像链接器通常在其他Unixen上所做的那样将调试信息链接到最终的二进制文件中。而是将调试信息保留在.o文件中,并在二进制文件中写入一个“调试图”,以告诉调试器如何查找和链接从.o文件读取的调试信息。当您剥离二进制文件时,调试映射也会被剥离。
因此,必须确保在最终链接之后不要移动或删除.o文件,并且在调试之前不要剥离正在调试的二进制文件。
您可以通过以下操作检查调试映射的存在:
$ nm -ap <PATH_TO_BINARY> | grep OSO
您应该看到如下输出:
000000005d152f51-03 0001 OSO /Path/To/Build/Folder/SomeFile.o
如果看不到可执行文件可能已被剥离。如果.o文件不存在,那么有人会比他们早应该清理了构建文件夹。
我也不知道gdb是否知道如何在macOS上读取调试映射。如果存在调试映射条目和.o文件,则可以尝试使用lldb,看看是否可以找到调试信息。如果可以,则可能是gdb-on-macOS问题。如果OSO和.o文件都存在,那么我无法猜测出了问题,可能值得向http://bugreporter.apple.com提交错误。