C/C++ recvmsg() 导致错误"检测到未对齐的缓存块",但 recv() 成功



当通过Epoll接收UDP数据包时,我观察到以下错误:

'unaligned tcache chunk detected'

我已经找到了代码的哪一部分,但它没有多大意义。

这是原始代码:

while (_listen)
{
const int count = epoll_wait(_epollFd, &events[0], MAX_SOCKETS, -1);
assert(count != -1);
for (int j = 0; j < count; ++j)
{
iovec iov;
char control[1024];
msghdr msg;
iov.iov_base = _buffer;
iov.iov_len = sizeof(_buffer);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_namelen = sizeof(sockaddr_in);
msg.msg_control = &control[0];
msg.msg_controllen = 1024;
const int sock = events[j].data.fd;
const int64_t n = recvmsg(sock, &msg, 0);   // This line seems to cause the problem
// More code
}
}

_buffer是一个类成员,声明为:char _buffer[65'536];

通过反复试验,我把问题缩小到这一行:

const int64_t n = recvmsg(sock, &msg, 0);

所以我用对::recv()的调用替换了::recvmsg(),它成功运行了:

while (_listen)
{
const int count = epoll_wait(_epollFd, &events[0], MAX_SOCKETS, -1);
assert(count != -1);
for (int j = 0; j < count; ++j)
{
const int sock = events[j].data.fd;
const int64_t n = recv(sock, _buffer, sizeof(_buffer), 0);
// More code
}
}

现在问题不发生了。是什么导致了这种情况?

我想知道为什么第一个代码不起作用。唯一的内存是_buffer,它不是手动分配的。

(不幸的是,由于环境/构建系统的原因,我不能使用消毒构建)。

在您的代码中,您忘记设置结构体msg的成员msg_name:

iovec iov;
char control[1024];
msghdr msg;
// add the following line:
sockaddr_in addr;
iov.iov_base = _buffer;
iov.iov_len = sizeof(_buffer);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = &control[0];
msg.msg_controllen = 1024;
// set the following members:
msg.msg_name = &addr;
msg.msg_namelen = sizeof(addr);
const int sock = events[j].data.fd;
const int64_t n = recvmsg(sock, &msg, 0);
// More code

内存损坏的原因是你有未定义的行为:recvmsg()试图写指针msg.msg_name,但后者包含一个未初始化的内存地址,所以recvmsg()实际上是在写一个无效的位置。

recvmsg()写入msg.msg_name内部发送消息的主机信息。

最新更新