CLang:在 std::thread 中运行函数会导致结构创建BAD_ACCESS



我最近从Kubuntu 16.04切换到Mac OS High Sierra,并开始移植我定期使用的部分代码。其中包括一个用于libsctp-dev的C++包装库。

我正在使用 SCTP 内核扩展来拥有与我的 Linux 机器上相同的 SCTP API。虽然 API 调用不会产生问题,但使用标准C++库提供的线程现在似乎会产生问题。该问题可以在以下代码片段中找到:

void Server::start(int32_t port) {
//This allocates the socket with the SCTP protocol assigned
Receiver::start();
//This function now binds the desired port to the created socket
this->_bind(port);
//Here I register handlers for network events that can occur
this->notificationHandler.setAssocChangeHandler(std::bind(&Server::handleAssocChange, this, _1));
this->notificationHandler.setShutdownEventHandler(std::bind(&Server::handleShutdownEvent, this, _1));
this->notificationHandler.setSendFailedHandler(std::bind(&Server::handleSendFailed, this, _1));
//This is the interesting part - this will lead to BAD_ACCESS
//exceptions in the receive function
dummy = this;
this->receiveThread = std::thread(dummyReceive);
//However, if I run it in the same thread, everything works fine
//(except that I need the receive loop to run in a separate thread)
//dummyReceive();
//This is the original call, I just used the dummy function to be
//sure that the bind function does not create the problem
//this->receiveThread = std::thread(std::bind(&Server::receive, this));
}

这是定义虚拟接收函数的部分:

Server *dummy = NULL;
void dummyReceive(){
dummy->receive();
}

最后,这是接收方法的代码(服务器是 Receiver 的子类,而 Receiver 又是 Endpoint 的子类(:

void Receiver::receive() {
uint8_t buffer[this->max_buffer_size];
uint32_t buffer_size = 0;
struct sockaddr_in peer_addr = {};
socklen_t peer_addr_size = sizeof(peer_addr);
struct sctp_sndrcvinfo info = {};
int32_t flags = 0;
while (this->can_receive) {
buffer_size = Endpoint::receive(buffer, max_buffer_size, peer_addr, peer_addr_size, info, flags);
if (buffer_size == 0) {
// Notification was sent
} else if (buffer_size == -1) {
CERR("Endpoint::receive(...) returned -1" << std::endl);
} else {
this->receiveCallback(buffer, buffer_size, peer_addr, peer_addr_size, info);
}
}
}

奇怪的是,当"peer_addr"初始化时,会发生BAD_ACCESS异常:

struct sockaddr_in peer_addr = {};

这是 CLion 给我的错误消息:

EXC_BAD_ACCESS (code=1, address=0x70000807bb88)

我可以通过在函数开始时初始化"peer_addr"和"info"结构来避免这种情况。但是,随后对"终结点::接收"的调用再次崩溃,并出现BAD_ACCESS异常。这次使用以下参数:

EXC_BAD_ACCESS (code=1, address=0x70000c4adb90)

有谁知道这里出了什么问题?我正在使用 Xcode 工具链 9.4.1(据我所知,它在内部使用 clang(和 CMake 3.12.0(我使用 CLion 作为 IDE(。如果有人需要完整的库代码,我可以将其上传到 git 并共享一个链接(目前它仅在私有 git 服务器上(。

最好 帕斯卡

如果max_buffer_size很大,您可能会遇到堆栈溢出。

堆栈的大小非常有限,在 OSX 上可能比在 Linux 上小(例如,默认的 pthread 堆栈大小仅为 512K https://developer.apple.com/library/archive/qa/qa1419/_index.html(。

大型缓冲区应由堆分配,而不是堆栈分配。

OSX不太擅长检测堆栈溢出,并且经常引发令人困惑的EXC_BAD_ACCESS错误,而不是更有用的堆栈溢出错误。

相关内容

  • 没有找到相关文章

最新更新