使用 openmp 锁的可疑分段错误
Suspicious Segmentation Fault using openmp locks
我的程序因分段错误而终止。我将代码缩减为:
#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 上编译:
System Version: OS X 10.11.6 (15G22010)
Kernel Version: Darwin 15.6.0
使用 g++-7
:
g++-7 (Homebrew GCC 7.5.0_1) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
命令行是
g++-7 file.cpp -O1 -fopenmp
-O2
和 -O3
也会出现分段错误,但不会出现 -O0
。 St运行gely,它只发生在这台机器和我其他机器的 none 或 godbolt.
I 运行 valgrind
在可执行文件上。这是输出:
==54305== Memcheck, a memory error detector
==54305== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==54305== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==54305== Command: ./a.out
==54305==
==54305== Invalid read of size 1
==54305== at 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== Address 0x4d55545a4d55545a is not stack'd, malloc'd or (recently) free'd
==54305==
==54305== Signal 11 being dropped from thread 0's queue
接着是
的无限循环
==54305== Signal 11 being dropped from thread 0's queue
之后我必须使用 kill
来停止 memcheck,它对 Ctrl+C
没有反应。另请参阅 this question,了解来自 valgrind
的类似回复。但是,这里似乎有不同的原因。
我目前无法使用 gdb
,因为我必须对其进行代码签名(我认为仅通过终端/ssh
是不可能的)。
另一个有趣的事情是,如果我注释掉行 ns3::somestruct cont("0", ns::A, ns::B, ns::C);
而不是简单地打印
Segmentation fault: 11
程序的输出变为
a.out(54371,0x7fff77d7d000) malloc: *** error for object 0x4d55545a4d55545a: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
我看不出分段错误从何而来。我错过了什么吗?
编辑
我已经设法 gdb
工作了。这是输出:
[New Thread 0x1703 of process 55870]
Program received signal SIGSEGV, Segmentation fault.
warning: `/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': can't open to read symbols: No such file or directory.
[Followed by a lot more warnings like that]
Program received signal SIGSEGV, Segmentation fault.
std::__cxx11::basic_string, std::allocator >::_M_construct (this=0x7fff5fbffb70, __beg=0x4d55545a4d55545a , __end=)
(gdb) where
#0 std::__cxx11::basic_string, std::allocator >::_M_construct (this=0x7fff5fbffb70, __beg=0x4d55545a4d55545a , __end=)
#1 0x0000000100000a2f in main (argc=, argv=) at /usr/local/Cellar/gcc@7/7.5.0_1/include/c++/7.5.0/bits/basic_string.h:236
我还是不明白,为什么会这样。我最近更新了自制软件 ,从那时起这个 "bug" 似乎发生了 ,从那时起这个错误就发生了。关于哪个图书馆可能需要更新或类似的任何想法?
编辑 2
同样,注释掉 main
的第一行移动了问题:
a.out(55934,0x7fff77d7d000) malloc: *** error for object 0x4d55545a4d55545a: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Program received signal SIGABRT, Aborted.
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 in ?? ()
编辑 3
otool -L
(ldd
在这台机器上不可用,但根据 this discussion 应该是等效的)给出以下输出:
a.out:
/usr/local/opt/gcc@7/lib/gcc/7/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.24.0)
/usr/local/opt/gcc@7/lib/gcc/7/libgomp.1.dylib (compatibility version 2.0.0, current version 2.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
/usr/local/lib/gcc/7/libgcc_s.1.dylib (compatibility version 1.0.0, current version 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 (compatibility version 7.0.0, current version 7.23.0)
而所有其他库都是相同的版本。此外,g++-9
编译的可执行文件还引用了版本 7.24.0。 也许这是导致错误的原因?
如何重新安装旧版本的 libstdc++ 来检验这个假设?
我强迫 brew 重新安装 g++
7.1.0 版,它使用 7.23.0 版的 libstdc++。该错误仍然存在。
经过多次尝试,我最终决定将操作系统升级到 macOS Mojave。在我 brew reinstall
ed everything 之后,这解决了问题。 (但是,请注意,valgrind
似乎还不适用于 Mojave。此外,我注意到其他软件(如 gnuplot)存在更多问题,程序无法正常启动。)
请注意,brew 警告我在旧 macOS 版本上尝试使用它时可能会出现问题,并且技术上不再支持它。此外,我更新了Xcode和clang
,它们也已经过时了很长时间。
因此,这个问题似乎是由 OS、brew/clang 和 gnu 编译器之间的某种版本不匹配引起的。
我的程序因分段错误而终止。我将代码缩减为:
#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 上编译:
System Version: OS X 10.11.6 (15G22010)
Kernel Version: Darwin 15.6.0
使用 g++-7
:
g++-7 (Homebrew GCC 7.5.0_1) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
命令行是
g++-7 file.cpp -O1 -fopenmp
-O2
和 -O3
也会出现分段错误,但不会出现 -O0
。 St运行gely,它只发生在这台机器和我其他机器的 none 或 godbolt.
I 运行 valgrind
在可执行文件上。这是输出:
==54305== Memcheck, a memory error detector
==54305== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==54305== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==54305== Command: ./a.out
==54305==
==54305== Invalid read of size 1
==54305== at 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== Address 0x4d55545a4d55545a is not stack'd, malloc'd or (recently) free'd
==54305==
==54305== Signal 11 being dropped from thread 0's queue
接着是
的无限循环==54305== Signal 11 being dropped from thread 0's queue
之后我必须使用 kill
来停止 memcheck,它对 Ctrl+C
没有反应。另请参阅 this question,了解来自 valgrind
的类似回复。但是,这里似乎有不同的原因。
我目前无法使用 gdb
,因为我必须对其进行代码签名(我认为仅通过终端/ssh
是不可能的)。
另一个有趣的事情是,如果我注释掉行 ns3::somestruct cont("0", ns::A, ns::B, ns::C);
而不是简单地打印
Segmentation fault: 11
程序的输出变为
a.out(54371,0x7fff77d7d000) malloc: *** error for object 0x4d55545a4d55545a: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
我看不出分段错误从何而来。我错过了什么吗?
编辑
我已经设法 gdb
工作了。这是输出:
[New Thread 0x1703 of process 55870]
Program received signal SIGSEGV, Segmentation fault.
warning: `/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': can't open to read symbols: No such file or directory.
[Followed by a lot more warnings like that]
Program received signal SIGSEGV, Segmentation fault.
std::__cxx11::basic_string, std::allocator >::_M_construct (this=0x7fff5fbffb70, __beg=0x4d55545a4d55545a , __end=)
(gdb) where
#0 std::__cxx11::basic_string, std::allocator >::_M_construct (this=0x7fff5fbffb70, __beg=0x4d55545a4d55545a , __end=)
#1 0x0000000100000a2f in main (argc=, argv=) at /usr/local/Cellar/gcc@7/7.5.0_1/include/c++/7.5.0/bits/basic_string.h:236
我还是不明白,为什么会这样。我最近更新了自制软件 ,从那时起这个 "bug" 似乎发生了 ,从那时起这个错误就发生了。关于哪个图书馆可能需要更新或类似的任何想法?
编辑 2
同样,注释掉 main
的第一行移动了问题:
a.out(55934,0x7fff77d7d000) malloc: *** error for object 0x4d55545a4d55545a: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Program received signal SIGABRT, Aborted.
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 in ?? ()
编辑 3
otool -L
(ldd
在这台机器上不可用,但根据 this discussion 应该是等效的)给出以下输出:
a.out:
/usr/local/opt/gcc@7/lib/gcc/7/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.24.0)
/usr/local/opt/gcc@7/lib/gcc/7/libgomp.1.dylib (compatibility version 2.0.0, current version 2.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
/usr/local/lib/gcc/7/libgcc_s.1.dylib (compatibility version 1.0.0, current version 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 (compatibility version 7.0.0, current version 7.23.0)
而所有其他库都是相同的版本。此外,g++-9
编译的可执行文件还引用了版本 7.24.0。 也许这是导致错误的原因?
如何重新安装旧版本的 libstdc++ 来检验这个假设?
我强迫 brew 重新安装 g++
7.1.0 版,它使用 7.23.0 版的 libstdc++。该错误仍然存在。
经过多次尝试,我最终决定将操作系统升级到 macOS Mojave。在我 brew reinstall
ed everything 之后,这解决了问题。 (但是,请注意,valgrind
似乎还不适用于 Mojave。此外,我注意到其他软件(如 gnuplot)存在更多问题,程序无法正常启动。)
请注意,brew 警告我在旧 macOS 版本上尝试使用它时可能会出现问题,并且技术上不再支持它。此外,我更新了Xcode和clang
,它们也已经过时了很长时间。
因此,这个问题似乎是由 OS、brew/clang 和 gnu 编译器之间的某种版本不匹配引起的。