两个线程之间是否有内存泄漏(缓冲,清空)
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' 同步和等待机制。
请考虑以下代码,包括两个线程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' 同步和等待机制。