During development of proprietary app. I have noticed memory leak, related to std::string in a MS Visual C++ 2013, Update 4.
Take a look at the following (basic) code prototype which causes memory leak:
static std::string MemoryLeakTest()
{
static size_t const test_size = 2002;
std::unique_ptr<char[]> result1(new char[test_size]);
std::string result2(result1.get(), test_size);
return result2;
}
calling it by:
std::string const testML = MemoryLeakTest();
std::cout << testML << std::endl;
Am I doing something wrong, or is it a memory leak in a Visual C++ STL?
P.S. this is DebugView output showing mem leak detected by VLD:
[11140] WARNING: Visual Leak Detector detected memory leaks!
[11140] ---------- Block 3 at 0x00A95620: 2002 bytes ----------
[11140] Leak Hash: 0x1DA884B6, Count: 1, Total 2002 bytes
[11140] Call Stack (TID 9568):
[11140] 0x0FF5C260 (File and line number not available): MSVCR120D.dll!operator new
[11140] f:\dd\vctools\crt\crtw32\stdcpp\newaop.cpp (6): TestCpp.exe!operator new[] + 0x9 bytes
[11140] c:\work\testcpp\testcpp.cpp (307): TestCpp.exe!MemoryLeakTest + 0xA bytes
[11140] c:\work\testcpp\testcpp.cpp (401): TestCpp.exe!wmain + 0x9 bytes
[11140] f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (623): TestCpp.exe!__tmainCRTStartup + 0x19 bytes
[11140] f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (466): TestCpp.exe!wmainCRTStartup
[11140] 0x75557C04 (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0x24 bytes
[11140] 0x77C4B54F (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x8F bytes
[11140] 0x77C4B51A (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x5A bytes
[11140] Data:
Tried your code with Deleaker and it couldn't find any leak.
Then tried this code:
while (true)
{
std::string const testML = MemoryLeakTest();
std::cout << testML << std::endl;
}
Task Manager shows that memory usage remains the same: no leaks.
I think this is a bug in VLD, you can find that std::unique_ptr really frees the memory, just step into during debugging, look:
~unique_ptr() _NOEXCEPT
{ // destroy the object
_Delete();
}
Go further:
void _Delete()
{ // delete the pointer
if (this->_Myptr != pointer())
this->get_deleter()(this->_Myptr);
}
};
Go further:
void operator()(_Ty *_Ptr) const _NOEXCEPT
{ // delete a pointer
static_assert(0 < sizeof (_Ty),
"can't delete an incomplete type");
delete[] _Ptr;
}
};
Aha, delete[] is called!
The call
std::unique_ptr<char[]> result1(new char[test_size]);
is correct. The tricky part is NOT to write std::unique_ptr<char>, which also compiles and can cause a memory leak (unique_ptr calls delete to release resource. When initialized with new[], we need to instruct unique_ptr to call the correct delete[]).
The std::string constructor call is also OK and it's very unlikely there's a memory leak. The std::string can be initialized from a C-style pointer in the same way.
I don't see any memory leak in your code snippet. How do you know it's a memory leak?
Related
I have an C++ application that has a main thread and a Poco::Timer to trigger a callback which writes to a file using Poco::FileOutputStream:
FileOutputStream file("test.txt", ios::binary); <-- *Access violation reading location here*
file.write(reinterpret_cast<char *>(&data), sizeof(data));
file.close();
The code always failed at the first line, here is the call stack:
testProject.exe!std::ctype::widen(char _Byte=' ') Line 1716 + 0xf bytes C++
testProject.exe!std::basic_ios >::widen(char _Byte=' ') Line 126 C++
testProject.exe!std::basic_ios >::init(std::basic_streambuf > * _Strbuf=0x038ef700, bool _Isstd=false) Line 135 + 0xa bytes C++
testProject.exe!std::basic_ostream >::basic_ostream >(std::basic_streambuf > * _Strbuf=0x038ef700, bool _Isstd=false) Line 54 C++
testProject.exe!Poco::FileOutputStream::FileOutputStream(const std::basic_string,std::allocator > & path="c:\Projects\TestProject\test.txt", int mode=32) Line 93 + 0xa3 bytes C++
testProject.exe!OPC_Server::OnTimer(Poco::Timer & timer={...}) Line 3656 + 0x13 bytes C++
testProject.exe!Poco::TimerCallback::invoke(Poco::Timer & timer={...}) Line 212 + 0x14 bytes C++
testProject.exe!Poco::Timer::run() Line 197 + 0x19 bytes C++
testProject.exe!Poco::PooledThread::run() Line 200 + 0x15 bytes C++
testProject.exe!Poco::`anonymous namespace'::RunnableHolder::run() Line 57 + 0x17 bytes C++
testProject.exe!Poco::ThreadImpl::runnableEntry(void * pThread=0x00db6afc) Line 207 + 0x20 bytes C++
testProject.exe!_callthreadstartex() Line 348 + 0xf bytes C
testProject.exe!_threadstartex(void * ptd=0x00db6d00) Line 331 C
Tracing into the stack, the timer thread seemed having problem reading the initialization _Byte at the top of the call stack in xlocale internal header:
_Elem __CLR_OR_THIS_CALL widen(char _Byte) const
{ // widen char
return (do_widen(_Byte)); <-- failed: Access violation reading location
}
Second entry in the stack in ios standard header:
_Elem __CLR_OR_THIS_CALL widen(char _Byte) const
{ // convert _Byte to character using imbued locale
const _Ctype& _Ctype_fac = _USE(getloc(), _Ctype);
return (_Ctype_fac.widen(_Byte)); <-- call the top of the stack
}
Third entry in the stack in ios standard header:
protected:
void __CLR_OR_THIS_CALL init(_Mysb *_Strbuf = 0,
bool _Isstd = false)
{ // initialize with stream buffer pointer
_Init(); // initialize ios_base
_Mystrbuf = _Strbuf;
_Tiestr = 0;
_Fillch = widen(' '); <-- call the second entry
But very strangely, the same code runs fine without any error when being used on the main thread.
Is there any permission settings that I need to set for the Poco::Timer to be able to function properly? Or am I missing something very obvious? Thanks for any help.
EDIT: ----------------------
Poco version: 1.7.3
Platform: windows
It turns out that the application exits immediately after the timer is created, but the exit is not cleanly done so it appears that the app is still running and the timer is still ticking, when actually some of the resource has already been released, which causes the error.
MS's _tmain() does something extra than main() apparently.
Sorry it is not _tmain(), but _tmainCRTStartup that is calling _tmain(). When _tmain() exits, other clean up code is run, my project isn't terminated somehow and the application appears still "running".
I'm getting some memory leaks in valgrind with strtok and I'm not sure why it's happening.
Possibly lost: 281 bytes in 8 blocks.
Still reachable: 64 bytes in 1 blocks.
I've also tried to call the function with a temporary char pointer instead of the one returned by getenv, but that didn't help.
void parsePath(const char * line, vector<string> &pathing) {
if (line == NULL)
return;
char * s = strdup(line);
if (!s)
exit(1);
char * pch;
pch = strtok(s, ":");
while (pch!=NULL) {
string tmp = string(pch);
pathing.push_back(tmp);
pch = strtok(NULL, ":");
}
free(s);
}
I call the function in my main with.
const char *pPath;
pPath = getenv("PATH");
if (pPath == NULL)
perror("PATH");
parsePath(pPath, pathing);
It's most likely a false positive from valgrind.
In general, memory leaks aren't a big problem in modern C++, but you're clearly using an older style. If you'd use just std::string and e.g. Boost.Tokenizer, there wouldn't be anything to leak.
According to the Visual C++ runtime there is a heap corruption when calling free in the destructor. But I don't understand why there is a heap corruption, can anyone explain why? The precise error is:
CRT detected that the application wrote to memory after end of heap buffer.
Also, if I ignore the error the program doesn't crash, it keeps running and when I press a key it returns 0.
The class only contains a constructor and destructor and the private vars FILE* target and char* raw_data.
foo::foo (wchar_t* path)
{
size_t size;
target = _wfopen (path, L"rb+");
if (!target) {
char* error = strerror (errno);
printf ("The file could not be opened: %s\n", error);
_exit (1);
}
fseek (target, 0L, SEEK_END);
size = ftell (target);
fseek (target, 0, SEEK_SET);
raw_data = (char*) malloc (size);
size = fread (raw_data, 1, size, target);
raw_data[size] = '\0';
}
foo::~foo ()
{
fclose (target);
free (raw_data);
}
int main ()
{
nbt* klas = new nbt (L"C:\\Users\\Ruben\\level");
puts ("Success?!");
delete klas;
getchar ();
return 0;
}
When writing the NUL terminator as you do:
raw_data[size] = '\0';
... you are using one byte more than the bytes you allocated. There may be other errors but there is definitely an error on this line -- writing to memory you have not allocated is "undefined behaviour" and could explain the crash you're observing.
One sure problem is this code:
raw_data = (char*) malloc (size);
size = fread (raw_data, 1, size, target);
raw_data[size] = '\0';
You cannot access raw_data[size], because it is beyond the allocated size. Indexed access in C/C++ is zero based. As a result, the last element of raw_data that can be accessed with your existing code is raw_data[size-1]. To be able to set the byte which is at offset size to zero you need to change your malloc to:
raw_data = (char*) malloc (size+1);
Since this is a C++ application, you may want to use streams and new/delete instead of FILE pointers and malloc/free.
I'm getting a memory leak from the following function:
int ReadWrite(int socket, char *readfile) {
FILE *rf = NULL;
rf = fopen(readfile, "rb");
fseek(rf, 0, SEEK_END);
int len = ftell(rf);
rewind(rf);
char readbuf[len + 1];
int res = fread(readbuf, len, 1, rf);
readbuf[len + 1] = '\0';
fclose(rf);
while (1) {
int wres = write(socket, readbuf, res);
if (wres == 0) {
cerr << "socket closed prematurely" << endl;
close(socket);
return EXIT_FAILURE;
}
if (res == -1) {
if (errno == EINTR)
continue;
cerr << "socket write failure: " << strerror(errno) << endl;
close(socket);
return EXIT_FAILURE;
}
break;
}
return EXIT_SUCCESS;
}
Valgrind tells me I leak the number of bytes that are in readfile (the actual file, not the name of readfile) through this operation:
Address 0x4c3b67e is 0 bytes after a block of size 14 alloc'd
at 0x4A07C84: operator new[](unsigned long) (vg_replace_malloc.c:363)
What's confusing me is I don't ever use new[] in my code. I checked fopen, ftell, and fread to see if they have hidden "gotcha's" where they call new[] somewhere but didn't find anything in the documentation on cplusplus.com. I've tried all different combinations of new char[]/delete[], malloc/free, and stack-allocated variables (above) but I get the same valgrind message every time. Any ideas? Thanks.
you call
char readbuf[len + 1];
and then later
readbuf[len + 1] = '\0';
wouldn't that overflow the array?
Well, you are declaring your readbuf array with non-constant size (i.e with run-time size). This is formally illegal in C++. Such feature exists in C99, but not in C++. Your code will not even compile in a pedantic C++ compiler. And your question is tagged [C++].
But it is quite possible that your compiler implements this feature as a non-standard extension, and that it creates such arrays through an implicit call to new[]. This is why you get the error message that refers to new[], even though you are not using new[] explicitly.
Of course, it is the compiler's responsibility to deallocate such arrays when they end their lifetime. I suspect that the compiler does all it has to do, but the valgrind is confused by something in compiler's actions, which makes it conclude that it is a memory leak.
Moreover, as others already noted, you are making out of bounds access to your array, which can also lead to absolutely any problems at run-time, including the strange report from valgrind.
I found out the problem actually had to do with the Makefile I was using. Thanks for the insight on my slip-up with the char[] bounds though!
I been working in a project that handles some char* pointers, and it's a requisite of the class to use char* instead of std::string, so...
I have this structure definition and this queue:
typedef struct packetQueue
{
char* buf;
int length;
packetQueue()
{
buf = new char[];
length = 0;
}
} PACKET;
concurrency::concurrent_queue IP_in_queue;
I have this buffer:
char sendBuf[MSG_SIZE + sizeof (IP_PACKET_HEADER_T) + 1]; // String to be send
and a structure for my new buffer:
PACKET ipQueue;
then I fill my buffer with this:
// 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;
And then I push my packet to my queue
IP_in_queue.push(ipQueue); // Push the buffer in the IP_in_queue
This is my loop just in case:
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
}
I know there is a memory leak in this procedure but I'm not sure.
When I push my packet, the buf pointer keeps pointing to my sendBuf, am I right? Because the assignment does that, but if I delete my pointer in the ipQueue after I push the program crashes. I have to say, after I push that struct into the queue, another thread try to pop that one, and obviously if I delete my ipQueue pointer I'll lost my buffer, so how can I avoid this memory leak?
Thanks
EDIT:
The memory leak using the definition of 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
First off; this isn't C, you're using a C++ compiler. structures in C cannot have methods and constructors and new and delete don't exist.
Secondly, you allocate memory for buf in your constructor, but then...
ipQueue.buf = sendBuf;
That's a leak. You need to call delete for every call to new. You allocate buf with new, but never call delete on it, so that memory is leaked.
I see no reason to allocate buf here. Just set it to null.
typedef struct packetQueue
{
char* buf;
int length;
packetQueue()
: buf(nullptr), length(0) { }
} PACKET;
On a side note, this is a very nasty mix of C and C++. Is this what your teacher is teaching you guys?
You've got a class (structure) with a constructor that allocates memory and no destructor that releases it, so you get memory leaks.
You also expose the buf member and assign to it; so your class has no control over whether the memory should be freed or not. But you need to free the memory allocated in the constructor before you assign to the buf the first time.
To get this right, you'll need to make the buf field private and add a destructor, a copy constructor and an assignment operator (and probably an accessor function). You'll still not be exception safe, though.
The problem you have is that you haven't looked at copy construction and copy assignment: when you push an object into a std::vector<T> it gets copied and the objects with the std::vector<T> get possibly moved around using assignment. The default generated copy constructor and copy assignment just copy or assign the respective members, i.e., whenever either copy is used, you'd end up with two objects pointing to the same buf. The first one destroyed would use delete[] buf; and all others would have a stale pointer which can't be deleted again. That is, you want to add three methods to your 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
};
To leverage the copy construction and destruction in the copy assignment, I find it useful to have a swap() member, because this is easily implemented and makes for a nice, simple copy assignment:
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;
}