【发布时间】:2021-06-18 21:15:39
【问题描述】:
基于building a .so that is also an executable,我正在尝试使用 C++ 进行重现,但在主程序执行时遇到了分段错误。
/* pie.cpp */
#include <cstdio>
int foo()
{
printf("in %s %s:%d\n", __func__, __FILE__, __LINE__);
return 42;
}
int main()
{
printf("in %s %s:%d\n", __func__, __FILE__, __LINE__);
return foo();
}
/* pie.h */
#ifndef PIE_H
#define PIE_H
int foo();
#endif
/* main.cpp */
#include <cstdio>
#include <string>
#include "pie.h"
std::string data;
int main()
{
data="TEST";
printf("in %s %s:%d [%s]\n", __func__, __FILE__, __LINE__, data.c_str());
return foo();
}
$ g++ -fPIC -pie -o pie.so pie.cpp -Wl,-E
$ g++ main.cpp ./pie.so
$ ./pie.so
in main pie.cpp:10
in foo pie.cpp:5
$ ./a.out
Segmentation fault (core dumped)
$
我将“数据”的定义从全局移动到它运行的本地。 似乎全局变量没有被初始化。
有人可以解释发生了什么以及应该做些什么来让它运行吗?
代码文件结果的gdb回溯:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 std::string::size (this=0x404080 <data>) at /usr/src/debug/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.h:716
716 { return _M_rep()->_M_length; }
(gdb) bt
#0 std::string::size (this=0x404080 <data>) at /usr/src/debug/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.h:716
#1 std::string::assign (this=0x404080 <data>, __s=0x402010 "TEST", __n=4) at /usr/src/debug/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.tcc:262
#2 0x00000000004011c5 in main () at main.cpp:9
谢谢!
【问题讨论】:
-
全局未初始化变量存储在 .bss 部分。如果在本地定义,变量存储在堆栈中。这就是区别。
-
构建一个调试版本并在调试器中运行它,看看有什么问题。我建议将
data.c_str()的结果分配给一个变量,并将此变量用于printf,以便更轻松地检查值。 -
感谢 Emre İriş。我知道,但问题是为什么在这种情况下会出现段错误?
-
@Bado,我添加了回溯核心文件的gdb结果以供参考。对于我在字符串中看到的段错误,但是为什么呢?
-
glibc 开发人员几年前决定不再支持带有入口点的
.sos。不写这个作为答案,因为显然我把我的书签放错了邮件列表讨论的地方。
标签: c++ linux shared-libraries glibc dlopen