我一直在处理一些char *指针的项目,并且这是使用char *而不是std :: string的类的必备条件,所以...
我有这个结构定义和这个队列:
typedef struct packetQueue
{
char* buf;
int length;
packetQueue()
{
buf = new char[];
length = 0;
}
} PACKET;
concurrency :: concurrent_queue IP_in_queue;
我有这个缓冲区:
char sendBuf[MSG_SIZE + sizeof (IP_PACKET_HEADER_T) + 1]; // String to be send
和我的新缓冲区的结构:
PACKET ipQueue;
然后我用这个填充我的缓冲区:
// Concatenates the header with sended message
memcpy(sendBuf, (void*)&sendHeader, sizeof(sendHeader));
memcpy(&sendBuf[sizeof(sendHeader)], readMessage, sendHeader.length);
ipQueue.buf = sendBuf;
ipQueue.length = packetSize;
然后我将数据包推送到队列中 IP_in_queue.push(ipQueue); //在IP_in_queue中推送缓冲区
这是我的循环以防万一:
while ( 1 )
{
// Get the user input
cout << "> ";
cin.getline (buf, BUFLEN);
IP_PACKET_HEADER_T sendHeader; // Store the header to be send
PACKET ipQueue;
char* fakeIPAddressDst, *readMessage;
delay = atoi(strtok (buf," ")); // Takes the first delay value
fakeIPAddressDst = strtok (NULL, " "); // Stores the IP Address
readMessage = strtok (NULL, " "); // Stores the sended message
Sleep(delay); // Sleep the miliseconds defined
// Fills the header with the data neccesary data
sendHeader.DIP = inet_addr(fakeIPAddressDst);
sendHeader.SIP = inet_addr(initAddress.fakeIpAddress);
sendHeader.length = getStringLength(readMessage) + 1;
packetSize = sizeof( sendHeader ) + sendHeader.length; // Defines the size of the packet to be send
// Concatenates the header with sended message
memcpy(sendBuf, (void*)&sendHeader, sizeof(sendHeader));
memcpy(&sendBuf[sizeof(sendHeader)], readMessage, sendHeader.length);
ipQueue.buf = sendBuf;
ipQueue.length = packetSize;
numbytes = packetSize; // The number of bytes of sended buffer
char sendedString[BUFLEN + 1]; // Variable for stores the data
IP_PACKET_HEADER_T readHeader; // To store the header for showing the information
// Print out the content of the packet
// Copy from buf to the header
memcpy( (void*)&readHeader, ipQueue.buf, sizeof( IP_PACKET_HEADER_T));
// Copy message part
memcpy( sendedString, &ipQueue.buf[sizeof(IP_PACKET_HEADER_T)], numbytes - sizeof(IP_PACKET_HEADER_T));
// Append \0 to the end
sendedString[numbytes - sizeof(IP_PACKET_HEADER_T)] = '\0';
// Save the IP information of the packet in a struct for print on the screen
struct in_addr fakeAddrHost;
fakeAddrHost.s_addr = readHeader.SIP;
// Print the neccesary data
cout << "[IN] DST: " << fakeIPAddressDst << endl; // Fake IP address of the destination
cout << "[IN] SRC: " << inet_ntoa(fakeAddrHost) << endl; // Fake IP address of the host
cout << "[IN] MSG: " << sendedString << endl ; // Message to send
IP_in_queue.push(ipQueue); // Push the buffer in the IP_in_queue
}
我知道这个程序有内存泄漏,但我不确定。 当我按下数据包时,buf指针一直指向我的sendBuf,对吗?因为赋值确实如此,但是如果我在推送程序崩溃后删除ipQueue中的指针。我不得不说,在我将该结构推入队列之后,另一个线程尝试弹出那个结构,显然如果我删除了我的ipQueue指针,我将丢失我的缓冲区,那么如何才能避免这种内存泄漏?
由于
编辑:
使用buf = nullptr
的定义进行内存泄漏---------- Block 1 at 0x0068BB30: 264 bytes ----------
Call Stack:
d:\program files (x86)\microsoft visual studio 11.0\vc\include\concurrent_queue.h (402): Host.exe!Concurrency::concurrent_queue<packetQueue,std::allocator<packetQueue> >::_Allocate_page + 0xF bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\concurrent_queue.cpp (113): MSVCP110D.dll!Concurrency::details::_Micro_queue::_Push + 0xD bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\concurrent_queue.cpp (232): MSVCP110D.dll!Concurrency::details::_Concurrent_queue_base_v4::_Internal_push
d:\program files (x86)\microsoft visual studio 11.0\vc\include\concurrent_queue.h (566): Host.exe!Concurrency::concurrent_queue<packetQueue,std::allocator<packetQueue> >::push + 0xF bytes
d:\users\silex rpr\documents\visual studio 2012\projects\project2\project2\host.cpp (802): Host.exe!main
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (536): Host.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (377): Host.exe!mainCRTStartup
0x7662339A (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
0x77179EF2 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
0x77179EC5 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
答案 0 :(得分:1)
首先关闭;这不是C,你使用的是C ++编译器。 C中的结构不能包含方法和构造函数,new
和delete
不存在。
其次,在构造函数中为buf
分配内存,但是......
ipQueue.buf = sendBuf;
那是泄密。每次拨打delete
时,您都需要致电new
。您使用buf
分配new
,但从不在其上调用delete
,以便泄露内存。
我认为没有理由在此处分配buf
。只需将其设置为null。
typedef struct packetQueue
{
char* buf;
int length;
packetQueue()
: buf(nullptr), length(0) { }
} PACKET;
另一方面,这是一个非常讨厌的C和C ++混合。这是你老师教给你们的吗?
答案 1 :(得分:0)
你有一个类(结构),它有一个构造函数来分配内存,没有析构函数释放它,所以你得到了内存泄漏。
您还会公开buf
成员并分配给它;所以你的班级无法控制是否应该释放内存。但是,在第一次分配给buf
之前,需要释放构造函数中分配的内存。
要做到这一点,你需要将buf
字段设为私有,并添加一个析构函数,一个复制构造函数和一个赋值运算符(可能还有一个访问函数)。不过,你仍然不会例外。
答案 2 :(得分:0)
您遇到的问题是您没有查看复制构造和复制分配:当您将对象推入std::vector<T>
时,它会被复制,而std::vector<T>
的对象可能会被移动使用作业。默认生成的复制构造函数和复制赋值只是复制或分配相应的成员,即,无论何时使用任何一个副本,最终都会有两个指向同一buf
的对象。第一个被破坏的将使用delete[] buf;
,而所有其他人将有一个陈旧的指针,不能再次删除。也就是说,您想为packetQueue
添加三种方法:
struct packetQueue
{
packetQueue(packetQueue const& other); // copy constructor: copies the content
packetQueue& operator= (packetQueue const& other); //copy assignment: updates the content
~packetQueue() // destructor: release the memory
void swap(packetQueue& other); // swap the content
// other members
};
为了在复制赋值中利用复制构造和销毁,我发现拥有swap()
成员很有用,因为这很容易实现,并且可以实现简单的复制分配:
void packetQueue::swap(packetQueue& other) {
std::swap(this->buf, other.buf);
std::Swap(this->size, other.size);
}
packetQueue& packetQueue::operator= (packetQueue const& other) {
packetQueue(other).swap(*this);
return *this;
}