作为家庭作业的一部分,我必须实施类似于facebook的东西。
以下代码行导致SG:
Tyler->addFriend(302); //Tyler asks Evil to be friends.
Evil->addFriend(1500); //Evil asks Tyler to be friends, resulting in both becoming friends.
以下是执行顺序中的相关方法: [ 1. Tyler通过服务器向Evil发送了一个朋友请求。 2.服务器将好友请求发送给Evil。 3.邪恶想要向泰勒发送朋友请求,但看到泰勒已经向他发送了朋友请求。邪恶接受了朋友的请求。]
void Fan::addFriend(int fanId){
shared_ptr<FanBookServer> server = FanBookServer::getServer();
shared_ptr<BaseRequest> request;
//Check if already friends.
if (friends.isIn(fanId)){
throw AlreadyFriendsException();
}
//Check if the other fan already send request.
try {
request = pendingRequests[fanId];
} catch (...){
//Make a friend request and send it to the server.
auto newRequest = std::make_shared<FriendRequest>(id, fanId);
server->fanToFanRequest(newRequest);
return;
}
request->accept();
}
void FanBookServer::fanToFanRequest(std::shared_ptr<BaseRequest> request){
std::shared_ptr<Fan> srcFan, dstFan;
try {
dstFan = connectedFans[request->getDestination()];
srcFan = connectedFans[request->getSource()];
} catch (mtm::MappingDoesntExist&){
throw UserNotConnectedException();
}
try {
dstFan->pendingRequests.insert(srcFan->getId(), request);
} catch (mtm::MappingAlreadyExists&){
throw AlreadySendRequestException();
}
}
void FriendRequest::accept() {
std::cout << "About to SG" << std::endl;
shared_ptr<FanBookServer> server = FanBookServer::getServer();
server->confirmFriendRequest(getSource(), getDestination());
}
编辑:
我用cout打印我的所有功能,并得出结论,SG在退出FanBookServer :: confirmFriendRequest()后立即发生。
以下cout行:
void FanBookServer::confirmFriendRequest(int sourceFan, int destinationFan){
std::cout << "Within FanBookServer::confirmFriendRequest" << std::endl;
std::shared_ptr<Fan> srcFan, dstFan;
std::cout << "before try" << std::endl;
try {
srcFan = connectedFans[sourceFan];
dstFan = connectedFans[destinationFan];
} catch (mtm::MappingDoesntExist&){
throw UserNotConnectedException();
}
std::cout << "After try" << std::endl;
std::cout << "Before insert" << std::endl;
srcFan->friends.insert(dstFan->getId(), dstFan);
dstFan->friends.insert(srcFan->getId(), srcFan);
std::cout << "After insert" << std::endl;
dstFan->pendingRequests.remove(srcFan->getId());
std::cout << "After PR" << std::endl;
}
[EDIT2:] 我运行LLDB并得到以下结果:
* thread #1: tid = 0x11ef4a, 0x0000000100004cea FanBook`std::__1::__shared_ptr_emplace<mtm::FriendRequest, std::__1::allocator<mtm::FriendRequest> >::__on_zero_shared(this=0x0000000100103fd0) + 42 at memory:3741, queue = 'com.apple.main-thread, stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x0000000100004cea FanBook`std::__1::__shared_ptr_emplace<mtm::FriendRequest, std::__1::allocator<mtm::FriendRequest> >::__on_zero_shared(this=0x0000000100103fd0) + 42 at memory:3741
3738 template <class _Tp, class _Alloc>
3739 void
3740 __shared_ptr_emplace<_Tp, _Alloc>::__on_zero_shared() _NOEXCEPT
-> 3741 {
3742 __data_.second().~_Tp();
3743 }
3744
我可以帮助我理解这里发生了什么吗?
答案 0 :(得分:0)
我认为您将srcFan
(和destFan
)声明为shared_ptr
并且您通过
srcFan = connectedFans[sourceFan];
connectedFans
中的内容是什么? shared_ptr
的数组/向量?或者只是普通指针的数组/向量(我敢打赌就是这种情况)。
如果是后一种情况,则会导致问题:因为srcFan
认为它拥有所引用对象的所有权,并且当它超出范围时,它会删除它。然后,当您下次访问connectedFans[sourceFan]
时,您正在访问一些释放的内存,这将导致seg错误。