c++ - 使用 openmp 锁的可疑分段错误
问题描述
我的程序因分段错误而终止。我将代码简化为:
#include <string>
#include <omp.h>
#include <iostream>
namespace ns { // Holds three strings
static const std::string A = "a";
static const std::string B = "b";
static const std::string C = "c";
}
namespace ns2 {
// Wraps an ostream and a lock; for example, concurrent access
// can be implemented this way
class wrapper {
private:
std::ostream &_stream;
omp_lock_t _lock;
public:
wrapper(std::ostream &stream) : _stream(stream)
{
omp_init_lock(&_lock);
}
// Segmentation Fault also occurs without destructor
~wrapper()
{
omp_destroy_lock(&_lock);
}
};
// Wrap stdout
static wrapper cout(std::cout);
}
namespace ns3 {
struct somestruct {
const std::string _0;
const std::string _a;
const std::string _b;
const std::string _c;
somestruct(std::string o, std::string a, std::string b, std::string c)
: _0(o), _a(a), _b(b), _c(c) { }
};
}
int main(int argc, char *argv[])
{
ns3::somestruct cont("0", ns::A, ns::B, ns::C);
return 0;
}
我在 MacOS 上编译:
系统版本:OS X 10.11.6 (15G22010)
内核版本:Darwin 15.6.0
使用g++-7
:
g++-7 (Homebrew GCC 7.5.0_1) 7.5.0
版权所有 (C) 2017 Free Software Foundation, Inc.
这是免费软件;查看复制条件的来源。没有
保修;甚至不考虑适销性或特定用途的适用性。
命令行是
g++-7 file.cpp -O1 -fopenmp
分段错误也发生在-O2
and-O3
上,但不发生在 上-O0
。奇怪的是,它只发生在这台机器上,而我的其他机器或Godbolt都没有。
我valgrind
在可执行文件上运行。这是输出:
==54305== Memcheck,内存错误检测器
==54305== 版权所有 (C) 2002-2017 和 GNU GPL,由 Julian Seward 等人提供。
==54305== 使用 Valgrind-3.15.0 和 LibVEX;使用 -h 重新运行版权信息
==54305== 命令:./a.out
==54305==
==54305== 大小为 1 的无效读取
==54305== 在 0x100000906:void std::__cxx11::basic_string , std::allocator >::_M_construct(char const*, char const*, std::forward_iterator_tag) [clone .isra.23] (basic_string.h:338)
==54305== by 0x1000009EC: main (basic_string.h :236)
==54305== 地址 0x4d55545a4d55545a 没有被堆栈、malloc 或(最近)释放
==54305==
==54305== 信号 11 正在从线程 0 的队列中删除
接着是一个无限循环
==54305== 信号 11 从线程 0 的队列中删除
之后我必须使用kill
停止 memcheck,它不会对Ctrl+C
. 另请参阅此问题以获取来自 的类似回复valgrind
。但是,这里似乎有不同的原因。
我目前无法使用gdb
,因为我必须对其进行代码设计(我认为仅通过 terminal/ 是不可能的ssh
)。
另一个有趣的事情是,如果我注释掉该行ns3::somestruct cont("0", ns::A, ns::B, ns::C);
而不是简单地打印
分段错误:11
程序的输出变为
a.out(54371,0x7fff77d7d000) malloc: *** 对象 0x4d55545a4d55545a 错误:未分配被释放的指针
*** 在 malloc_error_break 中设置断点以调试
Abort 陷阱:6
我看不出分段错误来自哪里。我错过了什么?
编辑
我已经设法开始gdb
工作了。这是输出:
[进程 55870 的新线程 0x1703]
程序收到信号 SIGSEGV,分段错误。
警告:`/private/tmp/gcc@7-20200229-63593-evr5eg/gcc-7.5.0/build/x86_64-apple-darwin15.6.0/libstdc++-v3/src/.libs/compatibility-atomic-c++ 0x.o':无法打开读取符号:没有这样的文件或目录。
[随后有更多类似的警告]
程序收到信号 SIGSEGV,分段错误。
std::__cxx11::basic_string, std::allocator >::_M_construct (this=0x7fff5fbffb70, __beg=0x4d55545a4d55545a , __end=)
(gdb) where
#0 std::__cxx11::basic_string, std::allocator >::_M_construct (这=0x7fff5fbffb70,__beg=0x4d55545a4d55545a,__end=)
#1 0x0000000100000a2f 在 /usr/local/Cellar/gcc@7/7.5.0_1/include/c++/7.5.0/bits/basic_string.h:236 的 main (argc=, argv=)
我还是不明白,为什么会这样。我最近更新了自制软件,从那时起这个“错误”似乎就发生了,从那时起这个错误就发生了。关于哪个库可能需要更新或类似的任何想法?
编辑 2
同样,注释掉第一行main
移动问题:
a.out(55934,0x7fff77d7d000) malloc: *** 对象 0x4d55545a4d55545a 的错误:未分配被释放的指针
*** 在 malloc_error_break 中设置断点以调试
程序收到信号 SIGABRT,中止。
0x00007fff88204f06 in __pthread_kill () from /usr/lib/system/libsystem_kernel.dylib
(gdb) where
#0 0x00007fff88204f06 in __pthread_kill () from /usr/lib/system/libsystem_kernel.dylib
#1 0x00007fff8c40d4ec in pthread_kill () from /usr/lib /system/libsystem_pthread.dylib
#2 0x00007fff8b7f06df in abort () from /usr/lib/system/libsystem_c.dylib
#3 0x00007fff88273041 in free () from /usr/lib/system/libsystem_malloc.dylib
#4 0x00007fff8b7f1463 in __cxa_finalize_ranges () from /usr/lib/system/libsystem_c.dylib
#5 0x00007fff8b7f1767 in exit () from /usr/lib/system/libsystem_c.dylib
#6 0x00007fff939de5b4 in start () from /usr/lib/system /libdyld.dylib
#7 0x0000000000000000 在 ?? ()
编辑 3
otool -L
(ldd
在这台机器上不可用,但根据这个讨论它应该是等效的)给出以下输出:
a.out: /usr/local/opt/gcc@7/lib/gcc/7/
libstdc++.6.dylib(兼容版本7.0.0,当前版本7.24.0)
/usr/local/opt/gcc@7/ lib/gcc/7/libgomp.1.dylib(兼容版本 2.0.0,当前版本 2.0.0)
/usr/lib/libSystem.B.dylib(兼容版本 1.0.0,当前版本 1226.10.1)
/usr/ local/lib/gcc/7/libgcc_s.1.dylib(兼容版本1.0.0,当前版本1.0.0)
我将添加重新安装后会发生的情况gcc@9
,但我记得从以前的安装中,行为应该是相同的。
行为与 相同g++-9
。otool -L
输出显示了 dylib 的版本 9 变体,除了在/usr/lib/libSystem.B.dylib
这种情况下是相同的。
任何人都可以重现这个错误吗?
编辑 4
我otool -L
在更新自制程序之前编译的旧版本的可执行文件上使用过。它引用
/usr/local/opt/gcc@7/lib/gcc/7/libstdc++.6.dylib(兼容版本7.0.0,当前版本7.23.0)
而所有其他库都是相同的版本。此外,g++-9
编译后的可执行文件还引用了 7.24.0 版本。也许这会导致错误?如何重新安装这个旧版本的 libstdc++ 来检验这个假设?
我强制 brew 重新安装g++
使用 libstdc++ 7.23.0 版本的 7.1.0 版本。该错误仍然存在。
解决方案
在我做了很多尝试之后,我最终决定将操作系统升级到macOS Mojave。brew reinstall
在我编辑完所有内容后,这解决了问题。(但是,请注意,valgrind
Mojave 似乎还不可用。此外,我注意到其他软件(例如 gnuplot)中存在更多问题,这些软件无法正常启动。)
请注意,brew 警告我尝试在旧 macOS 版本上使用它时可能会出现问题,并且在技术上不再支持它。此外,我更新了 Xcode 和clang
,它们也已经过时了很长时间。
因此,这个问题似乎是由操作系统、brew/clang 和 gnu 编译器之间的某种版本不匹配引起的。
推荐阅读
- javascript - 为什么 JQuery `attr()` 方法对我不起作用?
- excel - 当任何单元格处于编辑模式时从excel文件中获取数据
- java - 如何在 Java 类中访问 HTTP 请求
- c++ - 如何在 C++ 中的两个向量之间移动项目
- html - 随分辨率变化缩放背景图像
- javascript - 开玩笑测试失败 - 测试组件创建时返回未定义
- ruby-on-rails - 记录所有 Rack 中间件调用
- xcode - 如何使用自动布局 beta 7 UIKIT 修复 xcode 11 中可滚动内容大小的歧义
- function - 无法计算具有 6 个变量的最大化函数
- javascript - Cytoscape,如何突出显示点击的边缘?