Linux套接字和线程

时间:2018-11-22 07:27:54

标签: c++ linux multithreading sockets

我正在linux上写一些TCP服务器代码,它正与带有buildroot工具链的Pi交叉编译。基本上,我接受一个套接字,然后创建一个线程来侦听数据并对其进行处理。为了进行测试,我使用telnet作为客户端。有时,套接字关闭时,线程清理期间程序崩溃,我无法弄清原因。我最好的猜测是文件描述符怪异,但这在目前主要是猜测。

代码如下:

#include <algorithm>
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <map>
#include <set>
using namespace std;

int main(){
    set<string> exclusionSet;
    ifstream stopWords("stopwords.txt");
    copy(istream_iterator<string>(stopWords),
            istream_iterator<string>(),
            inserter(exclusionSet, exclusionSet.end()));

    stopWords.close();

    map<string, int> wordMap;
    ifstream words("sample_doc.txt");
    string s;

    while(words >> s) if (exclusionSet.count(s)==0) ++wordMap[s];

    ofstream out("frequency.txt");

    for_each(begin(wordMap),
            end(wordMap),
            [&out](const pair<const string, int>& e){ out<<e.first<<" "<<e.second<<endl;});
    out.close();
    return 0;
}

这是崩溃的回溯:

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?)

如果有人有任何想法,我将不胜感激!

2 个答案:

答案 0 :(得分:1)

正如已经告诉别人的那样,当您实际上需要new [] / delete []时,将new()与free()配对会导致崩溃。

但是,使用std::vector,您甚至不必自己进行内存分配。 (示例代码未编译/未测试)

void NetworkControl::worker(int sock)
{
    uint32_t n;

    std::vector<char> buf(200);

    while(1){
        n = read(sock, buf.data(), 199);
        if (n <= 0){
            break;
        }
        buf[n] = '\x00';
        printf("%s\n",buf.data());
    }
    close(sock);
}

对于buf,您还可以使用C样式的数组或std::array<char>,但随后必须确保没有堆栈溢出。

答案 1 :(得分:1)

free()函数释放ptr指向的内存空间,该空间必须由先前对malloc(),calloc()或realloc()的调用返回。其他-        明智的选择,或者如果以前已经调用过free(ptr),则会发生未定义的行为。如果ptr为NULL,则不执行任何操作。

但在您的代码上下文中:

字符* buf =新字符(200);

指针是由新函数获取的,它是C ++函数,这就是程序崩溃的原因。