两个线程之间是否有内存泄漏(缓冲,清空)

Is there any memory leak between two threads (Buffering, Emptying)

请考虑以下代码,包括两个线程buffering_thread(用一条消息填充缓冲区指针)和sending_thread(清空缓冲区):

#include "msg.cpp"

msg * buffer= NULL;
byte * send_bytes= NULL;
bool keep_buffering = true;
bool keep_sending = true;
int counter = 0;

void start_buffering() {
    while (keep_buffering){
        while (buffer != NULL && keep_buffering){}
        msg m (counter);
        buffer = &m;
        counter ++;
    }
    std::cout << "Finished start_buffering" << std::endl;
}

void sending() {
    while (keep_sending){
        if (counter > 10){
            keep_buffering = false;
            break;
        }
        if (buffer != NULL){
            HeaderType messageHeader = buffer -> getHeader();
            print(messageHeader);
            send_bytes = (byte *) realloc(send_bytes,DATASIZE + HEADER);
            memcpy (send_bytes, &messageHeader, HEADER);
            memcpy (send_bytes + HEADER,buffer -> getText(), DATASIZE);
            // Do something, suppose for now NOTHING
            free (buffer -> getText());
            buffer = NULL;
        }
    }
    std::cout << "Finished sending" << std::endl;
}

int main () {

    std::thread sending_thread(sending);

    std::thread buffering_thread(start_buffering);

    buffering_thread.join();

    keep_sending = false;

    sending_thread.join();

    //free (buffer);
    free (send_bytes);
    return 0;
}

其中class msg如下:

#include <iostream>
#include <stdlib.h>
#include <cstring>
#include <mutex>
#include <thread>
#define DATASIZE 10
#define HEADER sizeof(HeaderType)

class msg
{
    private:
        HeaderType header;
        byte * text;    

    public:
        msg(int ID);
        HeaderType getHeader();
        byte * getText();
};

msg::msg(int ID){
    header.mID = ID;
    text = (byte *)malloc (DATASIZE);
    memset (text, '.', DATASIZE);
}

HeaderType msg::getHeader(){
    return header;
}


void print(HeaderType header) {
    std::cout << "Message ID: " << header.mID << std::endl;
}


byte * msg::getText(){
    return text;
}

这是HeaderType:

typedef struct {
    int mID;
}HeaderType;

Valgrind 报告:

==3809== 20 bytes in 2 blocks are definitely lost in loss record 1 of 1
==3809==    at 0x4028876: malloc (vg_replace_malloc.c:236)
==3809==    by 0x80492BD: msg::msg(int) (in /home/linux/LCR-write/src/test)
==3809==    by 0x8049384: start_buffering() (in /home/linux/LCR-write/src/test)

确实,我猜这段代码中一定没有内存泄漏。缓冲区应始终由 sending_thread 清空。请哪位大侠指出错误。

你需要一个 msg 的析构函数来释放在构造函数中为文本分配的内存

class msg
{
    private:
        HeaderType header;
        byte * text;    

    public:
        msg(int ID);
        HeaderType getHeader();
        byte * getText();
        ~msg() {free(text);}
};

问题出在 start_buffering() 函数中。

while (keep_buffering){
    msg m (counter);
    while (buffer != NULL && keep_buffering){}
    buffer = &m;
    counter ++;
}

这个循环创建一个 msg 并在其构造函数中为 text 分配内存。然后它等待,然后它将执行:

    buffer = &m;
    counter ++;
    // end of loop
    msg m (counter);

当循环到达终点时,它开始下一次迭代而不等待任何东西。 'old' msg m 超出范围,新的 msg m 被分配在堆栈上与旧的完全相同的位置。所以指针 buffer 仍然是 'valid'(不是真的!),指向新的 m。结果是第一个 msg m 的内存泄漏,更重要的是 未定义的行为 。您不能再使用不在范围内的东西。

此外,我建议使用 'official' 同步和等待机制。