【发布时间】:2019-04-24 20:02:26
【问题描述】:
我正在 Linux 上编写一些 TCP 服务器代码,它正在为带有 buildroot 工具链的 Pi 进行交叉编译。基本上我接受一个套接字然后创建一个线程来监听数据并处理它。为了测试,我使用 telnet 作为客户端。有时,当套接字关闭时,程序在线程清理期间崩溃,我不知道为什么。我最好的猜测是文件描述符的怪异,但目前这主要是猜测。
代码如下:
void NetworkControl::startListening()
{
mListenThread = std::thread(listener);
mListenThread.detach();
}
void NetworkControl::listener()
{
int sockfd, newsockfd, clilen;
struct sockaddr_in serv_addr, cli_addr;
int portno = 612;
std::thread mWorkThread;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{} //print error
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
{ }//print error
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr, (socklen_t*) &clilen);
if (newsockfd < 0) {
//print error
}else{
mWorkThread = std::thread(worker,newsockfd);
mWorkThread.detach();
}
}
}
void NetworkControl::worker(int sock)
{
uint32_t n;
char *buf = new char(200);
while(1){
n = read(sock,&buf[0],199);;
if (n <= 0){
goto exit;
}
buf[n] = '\x00';
printf("%s\n",buf);
}
exit:
free(buf);
close(sock);
}
这是崩溃的回溯:
#0 0x767c4e0c in raise () from /home/david/Desktop/BR-Pi2/output/host/arm-buildroot-linux-gnueabihf/sysroot/lib/libc.so.6
#1 0x767c60e4 in abort () from /home/david/Desktop/BR-Pi2/output/host/arm-buildroot-linux-gnueabihf/sysroot/lib/libc.so.6
#2 0x767fe2c8 in __libc_message () from /home/david/Desktop/BR-Pi2/output/host/arm-buildroot-linux-gnueabihf/sysroot/lib/libc.so.6
#3 0x76804790 in malloc_printerr () from /home/david/Desktop/BR-Pi2/output/host/arm-buildroot-linux-gnueabihf/sysroot/lib/libc.so.6
#4 0x76805850 in _int_free () from /home/david/Desktop/BR-Pi2/output/host/arm-buildroot-linux-gnueabihf/sysroot/lib/libc.so.6
#5 0x768a3c78 in tcache_thread_freeres () from /home/david/Desktop/BR-Pi2/output/host/arm-buildroot-linux-gnueabihf/sysroot/lib/libc.so.6
#6 0x768a3cdc in __libc_thread_freeres () from /home/david/Desktop/BR-Pi2/output/host/arm-buildroot-linux-gnueabihf/sysroot/lib/libc.so.6
#7 0x76f01f3c in start_thread () from /home/david/Desktop/BR-Pi2/output/host/arm-buildroot-linux-gnueabihf/sysroot/lib/libpthread.so.0
#8 0x768683b8 in ?? () from /home/david/Desktop/BR-Pi2/output/host/arm-buildroot-linux-gnueabihf/sysroot/lib/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
控制台输出:
free() invalid next size (fast)
如果有人有任何想法,我将不胜感激!
【问题讨论】:
-
我假设
NetworkControl::listener是static成员函数?您可以尝试创建一个minimal reproducible example 向我们展示吗? -
至于您收到的消息,通常是在您写入超出分配内存的范围时。使用例如Valgrind 帮助您了解更多信息。
-
提示:
new char(200)分配了一个singlechar,并将其初始化为值200。 -
此外:始终将
new与delete匹配,将new[]与delete[]匹配。也许您应该退后几步,find a good book or two 并阅读有关动态内存分配的更多信息(以及更多有关 IMO 的内容)?或者更好的是,对所有字符串使用std::string。 -
最后,永远不要使用
goto和标签。如果您需要跳出循环,请使用break。
标签: c++ linux multithreading sockets