Linux сокеты и потоки - PullRequest
       3

Linux сокеты и потоки

0 голосов
/ 22 ноября 2018

Я пишу некоторый код TCP-сервера для Linux, он кросс-компилируется для Pi с цепочкой инструментов buildroot.По сути, я принимаю сокет, а затем создаю поток для прослушивания данных и их обработки.Для тестирования я использую 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)

Если у кого-то есть идеи, я буду признателен за это!

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Функция free () освобождает пространство памяти, на которое указывает ptr, которое должно быть возвращено предыдущим вызовом malloc (), calloc () или realloc ().В противном случае или, если free (ptr) уже был вызван ранее, происходит неопределенное поведение.Если ptr равен NULL, никакие операции не выполняются.

но в контексте вашего кода:

char * buf = new char (200);

указатель получен новой функцией, это функция C ++, поэтому вашСбой программы.

0 голосов
/ 22 ноября 2018

Как уже говорилось другим, сбой вызван сопряжением new () с free (), в то время как вы фактически нуждались в new [] / delete [].

Однако, используя 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>, но тогда вам нужно убедиться, что вы не получаете переполнение стека.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...