Memory Leak During Push In A Queue

c, c++, memory-leaks, queue

Solution

At the beginning of `while ( 1 )` loop in `PHY_in_Thread()` you allocate `recBuf`:

char* recBuf = new char[BUFLEN + 1];

but at the end of the loop body, you miss to free it; you just leak the memory due to `recBuf = nullptr;` assignment.

Instead, try with proper `recBuf` deletion at the end of loop body:

delete [] recBuf;
recBuf = nullptr;

Problem

I been working in a project for my Data Networks course and I encounter a memory leak but I don't understand why it's happening. By the way, I know there is a awful mix of C and C++, but I can't do anything about it, it's based on class code and I can't modified that, I know that this is not a good way to do it and I need to use char* as requisite. My program it's multithreaded and I handle this struct: ``` typedef struct packetQueue { char* buf; int length; packetQueue() { buf = nullptr; length = 0; } packetQueue(char* buffer, int len) { length = len; buf = new char[length + 1]; memcpy(buf, buffer, len); buf[length] = '\0'; } packetQueue(const packetQueue& other) { length = other.length; if (other.buf) { buf = new char[length + 1]; memcpy(buf, other.buf, length); buf[length] = '\0'; } else { buf = nullptr; } } packetQueue& operator=(const packetQueue& that) { if (this == &that) { return *this; } delete[] buf; length = that.length; if (that.buf) { buf = new char[length + 1]; memcpy(buf, that.buf, length); buf[length] = '\0'; } else { buf = nullptr; } return *this; } ~packetQueue() { delete[] buf; buf = nullptr; } } PACKET; ``` In my constructor with two parameters I do that assignment because the push of my queue does a deep copy of my struct and like I have my copy constructor and I already handled that. So, I have one thread (I been testing one by one, and the VLD results are just for this one). ``` DWORD _stdcall PHY_in_Thread(void* data) { int numbytes, counter = 0; SOCKET hostSocket = *(SOCKET*) data; // Socket where the host receives struct sockaddr_in si_recvfrom; struct sockaddr_storage their_addr; socklen_t addr_len; addr_len = sizeof their_addr; while ( 1 ) { char* recBuf = new char[BUFLEN + 1]; // Checks if it's any buffer on the socket to be processed if ( (numbytes = recvfrom(hostSocket, recBuf, BUFLEN, 0, (sockaddr*) &si_recvfrom, &addr_len)) == -1) { cerr << "Could not receive datagram." << endl; delete[] recBuf; closesocket(hostSocket); WSACleanup(); exit(0); } recBuf[numbytes] = '\0'; // append NULL to the end of the string char* temporalBuffer = new char[numbytes - CHECKSUM_MAX_SIZE + 1]; memcpy(temporalBuffer, recBuf, numbytes - CHECKSUM_MAX_SIZE); temporalBuffer[numbytes - CHECKSUM_MAX_SIZE] = '\0'; char extractedChecksum[CHECKSUM_HEX_SIZE + 1]; DWORD crcBuffer = crc32buf(temporalBuffer, numbytes- CHECKSUM_MAX_SIZE); // Calculates the CRC32 checksum _snprintf(extractedChecksum, 8 , "%08lX", crcBuffer); // Prints the string in a buffer extractedChecksum[CHECKSUM_HEX_SIZE] = '\0'; delete[] temporalBuffer; string strExtractedChecksum = extractedChecksum; // Copies the array in a string transform(strExtractedChecksum.begin(), strExtractedChecksum.end(), strExtractedChecksum.begin(), upper); // Uppercase the string // Array for store the checksum of the packet char readChecksum[CHECKSUM_MAX_SIZE + 1]; // Store the checksum of the packet in local variable memcpy( readChecksum, &recBuf[numbytes - CHECKSUM_MAX_SIZE], CHECKSUM_MAX_SIZE); readChecksum[CHECKSUM_MAX_SIZE] = '\0'; std::stringstream stream; string strReadChecksum; for (int i = 0; i < CHECKSUM_MAX_SIZE; i++ ) { int number = static_cast<int>(readChecksum[i]); // Casts every character of the checksum array if ( readChecksum[i] <= -1 ) // In case the int value it's negative adds the constant value to make that recognizable { number += 256; } // Convert the decimal number in a hex representation stream.str(""); stream << hex << number; if ( stream.str().length() < 2 ) // In case it's a number less than 10, adds a 0 at the beginning { strReadChecksum += "0" + stream.str(); } else { // Working out the presentation of the number strReadChecksum += stream.str(); } } std::transform(strReadChecksum.begin(), strReadChecksum.end(), strReadChecksum.begin(), upper); // Uppercase the string strReadChecksum[CHECKSUM_HEX_SIZE] = '\0'; cout << "[PI] Frame #" << counter <<" received ("<< numbytes <<" bytes). " << endl; if ( !strcmp(strReadChecksum.c_str(), extractedChecksum) ) // Checks if the CRC are equal { cout << "[CRC] Checksum OK: 0x" << extractedChecksum << endl; } else { cout << "[CRC] Checksum failure: 0x" << extractedChecksum << endl; } // Push the packet in the MAC_in_queue to be processed MAC_in_queue.push(PACKET(recBuf, numbytes)); recBuf = nullptr; counter++; break; // Just for test one packet } MAC_in_queue.clear(); return 0; ``` } But when I execute this thread and send something to this thread to be stored in this queue gives a leak. In this execution there is only one item to make things simple. ``` ---------- Block 29 at 0x0068F718: 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 (240): MSVCP110D.dll!Concurrency::details::_Concurrent_queue_base_v4::_Internal_move_push d:\program files (x86)\microsoft visual studio 11.0\vc\include\concurrent_queue.h (581): Host.exe!Concurrency::concurrent_queue<packetQueue,std::allocator<packetQueue> >::push + 0xF bytes d:\users\silex rpr\documents\visual studio 2012\projects\project3\hoster\host.cpp (638): Host.exe!PHY_in_Thread + 0x3D bytes 0x7474339A (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes 0x76EC9EF2 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes 0x76EC9EC5 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes Data: 00 00 00 00 01 00 00 00 60 F8 68 00 80 00 00 00 ........ `.h..... CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........ ``` But I don't understand where it's this data leaking, I hope I made myself clear. Thanks beforehand

Original source