gpt4 book ai didi

c++ - segmentation fault,可能原因: function pointer, 多线程,STL map等

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:44:56 27 4
gpt4 key购买 nike

我是 C++ 新手。我不知道为什么下面的代码有段错误。 Doo() 是一个包含 map<> 的类。您可以调用 Doo::start() 来启动 while 循环线程。然后调用 Doo::turnoff() 终止线程。我不知道我的代码有什么问题。请帮助我理解。

#include <iostream>
#include <thread>
#include <map>
#include <chrono>


using namespace std;

class Doo{
int id;
bool _turnoff=false;
map<int,string> msg;
public:
Doo(int _id);
void start(bool (*fptr)(map<int,string>&));
void turnoff();
};

Doo::Doo(int _id){
id = _id;
msg[1]="hello";
msg[2]="nihao";
msg[4]="conichiwa";
}

void Doo::start(bool (*fptr)(map<int,string>&)){
thread m_thr([&](){
while(!_turnoff){
this_thread::sleep_for(chrono::seconds(1));
fptr(msg);
}
});
m_thr.detach();
}

void Doo::turnoff(){
_turnoff=true;
}

bool hdl(map<int,string>& greet){
cout<<greet[2]<<endl;
return true;
}

int main(void){
Doo d(1);
d.start(hdl);
while(1){
char x;
cin>>x;
if(x=='q'){
cout<<"quit"<<endl;
d.turnoff();
this_thread::sleep_for(chrono::seconds(1));
break;
}
}
return 0;
}

我用下面的命令编译:

g++ p3.cpp -std=c++11 -pthread

编译没有问题

valgrind 结果:

==18849== Memcheck, a memory error detector
==18849== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==18849== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==18849== Command: ./a.out
==18849==
==18849==
==18849== Process terminating with default action of signal 11 (SIGSEGV)
==18849== Bad permissions for mapped region at address 0x68C1700
==18849== at 0x68C1700: ???
==18849== by 0x402799: void std::_Bind_simple<Doo::start(bool (*)(std::map<int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<int>, std::allocator<std::pair<int const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&))::{lambda()#1} ()>::_M_invoke<>(std::_Index_tuple<>) (in /home/xli1989/Projects/playground/a.out)
==18849== by 0x4026EF: std::_Bind_simple<Doo::start(bool (*)(std::map<int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<int>, std::allocator<std::pair<int const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&))::{lambda()#1} ()>::operator()() (in /home/xli1989/Projects/playground/a.out)
==18849== by 0x40267F: std::thread::_Impl<std::_Bind_simple<Doo::start(bool (*)(std::map<int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<int>, std::allocator<std::pair<int const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&))::{lambda()#1} ()> >::_M_run() (in /home/xli1989/Projects/playground/a.out)
==18849== by 0x4EF2C7F: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==18849== by 0x53D96F9: start_thread (pthread_create.c:333)
==18849== by 0x56F5B5C: clone (clone.S:109)

最佳答案

首先,_turnoff 上存在数据竞争,因此您的示例将显示 UB。请记住,nothing 在 C++ 中默认是原子的,因此您最好使用 std::atomic 或同步。


现在,您所指的问题是由线程任务获取对主线程分配的自动对象 (Doo::msg) 的引用引起的.由于工作线程与其在主线程中的句柄分离,这意味着主线程将能够在工作线程之前终止并销毁堆栈上所有分配给它的对象(main destroys它自己的堆栈)。这导致工作线程可能保留对已销毁对象的引用。

在 main 中发送关闭信号后,您只等待/ sleep 与工作线程循环中的等待/ sleep 相同的时间。因此,工作线程很有可能使用悬挂引用“最后完成”。

这通常不是问题,因为程序无论如何都会终止,但 Valgrind 仍会报错。

关于c++ - segmentation fault,可能原因: function pointer, 多线程,STL map等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40822481/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com