Heap corruption in code - c++

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.

Related

Concat two strings in C and allocate dynamically buffer

I know this kind of question has already been asked. I also used the solution of this topic to my tests. However, I want to know how using this kind of function without memory leak neither exception.
Note:
LPTSTR ~ char* and
LPCTSTR ~ const char*
void add_to_buffer(LPTSTR* buffer, LPCTSTR msg) {
// Determine new size
int newSize = 0;
// Allocate new buffer
if (*buffer == NULL)
newSize = _tcsclen(msg) + 1; // strlen()
else
newSize = _tcslen(*buffer) + _tcsclen(msg) + 1;
LPTSTR newBuffer = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newSize); // malloc()
// Do the copy and concat
if (*buffer == NULL)
_tcscpy(newBuffer, msg); // strcpy()
else
{
_tcscpy(newBuffer, *buffer);
_tcscat(newBuffer, msg); // strcat()
// release old buffer
HeapFree(GetProcessHeap(), 0, *buffer); // free()
}
// store new pointer
*buffer = newBuffer;
}
Tests:
LPTSTR test = NULL;
add_to_buffer(&test, _T("User:\r\n"));
add_to_buffer(&test, _T("42"));
First call to add_to_buffer works. However, the second function call causes an exception at HeapFree. I'm sure this is a problem about pointers, but I do not understand how to fix it.
Is it a good method? How to fix my exception?
If you are compiling the code as multi-byte application this line
LPTSTR newBuffer = (LPTSTR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
newSize
);
might allocate to few memory.
To fix this use:
LPTSTR newBuffer = (LPTSTR)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
newSize * sizeof(*newBuffer)
);
Besides this and the fact that the code lacks error checking for system calls the code looks fine.
However, to simplify things one can use HeapReAlloc() instead of the combination of HeapAlloc() and HeapFree().
If the program crashes anyway this might due to the memory management already being mashed up before this actual crash you observe.
If your program is unicode-enabled, you're not allocating enough memory - because string length (in symbols) and string size (in bytes) don't match.
If it isn't, I don't see reason of using non-standard-C types over standard ones. It shouldn't be a problem though.

Memory leak through new[] without ever calling new

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!

new and malloc allocates extra 16 bytes

I'm writing on c++ in VS2010 Windows 7. I try to read file of size 64 bytes. Here's the code:
BYTE* MyReadFile(FILE *f)
{
size_t result;
BYTE *buffer;
long lSize;
if (f == NULL)
{
fputs ("File error", stderr);
exit (1);
}
fseek (f, 0, SEEK_END);
lSize = ftell (f);
rewind (f);
//buffer = (BYTE*) malloc (sizeof(char)*lSize);
buffer = new BYTE[lSize];
if (buffer == NULL)
{
fputs ("Memory error", stderr);
exit (2);
}
result = fread (buffer, 1, lSize, f);
if (result != lSize)
{
fputs ("Reading error",stderr);
exit (3);
}
fclose (f);
return buffer;
}
When I get file size it is 64, but when I allocate memory for it with new BYTE[lSize] I get 80 bytes of space and thus strange sequence ээээ««««««««оюою is added to the end of buffer. Can you please tell me how to handle this?
There is an important difference between the number of bytes you have allocated, and the number of bytes that you see.
If lsize is 64, you have indeed allocated yourself 64 bytes. This does not mean that behind the screen the C++ run time will have asked exactly 64 bytes to Windows. In practice memory managers ask slightly more memory so they are able to do their own homework. Often these extra bytes are allocated BEFORE the pointer you get back from new/malloc so you will never see them.
However, that is not your problem. The problem is that you read 64 bytes from file using fread. There is no way that fread knows what kind of data you are reading. It could be a struct, a char buffer, a set of doubles, ... It just reads these bytes for you.
This means that if the file contains the characters "ABC" you will get exactly "ABC" back. BUT, in C, strings should be nul-terminated, so if you pass this buffer to printf, it will continue to scan memory until it finds a nul-character.
So, to solve your problem, allocate 1 byte more, and set the last byte to the nul character, like this:
buffer = new BYTE[lSize+1];
buffer[lSize] = '\0';
What is behind and above is called sentinel.It is used to check if your code does not exceed boundary of allocated memory.When your program overwrite this values, CRT library will report debug messages when you release your buffer.
Look here : http://msdn.microsoft.com/en-us/library/ms220938%28v=vs.80%29.aspx
Although this may look like a memory problem, its actually a printing problem (as #Mystical pointed out). You need to put a null termination if you are going to print out anything as a string, else memory will be wildy read till one is encountered (which is UB).
Try this instead:
buffer = new BYTE[lSize + 1];
if (buffer == NULL)
{
fputs ("Memory error", stderr);
exit (2);
}
result = fread (buffer, 1, lSize, f);
if (result != lSize)
{
fputs ("Reading error",stderr);
exit (3);
}
buffer[lSize] = '\0';
It'll ensure there is a null terminator at the end of the returned buffer.
When memory is allocated, it is not on a per byte basis. Instead it is allocated in aligned blocks of 8 or 16 bytes (possibly with a header at the start, before the pointer). This is usually not a problem unless you create lots (many millions) of little objects. This doesn't have to be a problem in C and isn't even a major problem in Java (which doesn't support array of objects or objects allocated on the stack).

Heap memory allocation crash with std::wstring

I have a big problem with std::wstring memory allocation. The program crash when I try to use this code:
size_t size;
mbstowcs_s(&size, NULL, 0, buffer, _TRUNCATE);
wchar_t *buffer2 = (wchar_t*)malloc(size + 1);
mbstowcs_s(&size, buffer, buffer_size, buffer, _TRUNCATE);
buffer2[size] = '\0';
std::wstring data(buffer);
the crash is on the last line and doesn't happen if I use the following line:
std::wstring data(L"hello");
the error is memory heap allocation failure and the result is the crash of the program. Why? What's wrong?
wchar_t *buffer2 = (wchar_t*)malloc((size + 1) * sizeof(wchar_t));
^^^^^^^^^^^^^^^^^
malloc allocates a number of bytes - you wan't a number of wchar_t's
If you're using c++, the correct way is:
wchar_t *buffer2 = new wchar_t[size+1];
If you use std::wstring I assume you are using C++, dont use malloc, use new & delete (just a side note)
std::vector seems to be a good way to make a buffer here. Its constructor receives elements number (not bytes) and you don't have to remember to delete the memory.

Memory allocation problem

I'm writing a Windows Service that allocates memory dynamically. I tried both c++'s new operator and C's malloc. They return (probably valid) pointer but when I try to dereference it the program crashes with Windows saying:
The instruction at "0x77c478ac"
referenced memory at "0x00cb9001". The
memory could not be "read".
BTW I guess the pointer is valid because the referenced memory is not NULL (0x00cb9001).
EDIT: Here is the code
/* This is a thread procedure that is
called when connection arrives
and its purpose is to serve as a
regular expression server.
*/
void threadProc(LPVOID *ptr){
SOCKET accSock = (SOCKET) *ptr;
void * foundPtr;
int recvdBytes;
char * literalPtr;
u_long iMode = 0;
literalPtr = new char [4096]; //this may cause the problem
//We allocate 4kb but in fact the first 2 kbs will be for
//for the literal string, the next 2 kb are for the result
//that must be returned
ioctlsocket(accSock, FIONBIO, &iMode); //the "parent" socket was nonblocking
if(literalPtr){
recvdBytes = recv(accSock, (literalPtr+1), 2048, 0); //BTW, recv returns -1
foundPtr = regexp_cmp(literalPtr, fBuffer, 0); //program crashes when calling this function
if(!foundPtr){
*(literalPtr+2048) = (int) 0;
send(accSock, (char *) (literalPtr+2048), 4, 0); //sending 4 NULLs
}
else {
send(accSock, (char *) (literalPtr+2048), 2048, 0);
}
shutdown (accSock, 0);
delete[] literalPtr;
return;
}
It's pretty funny, you have the answer commented in your code. recv returns -1, indicating that no bytes were read and there is an error, (why not check errno and see what the problem is?) and then you call regexp_cmp anyway on an uninitialized buffer. No wonder it crashes.
As a second point, your code it overly complex. For example, the buffer size is fixed. Why bother newing it? You can keep the buffer on the stack. Why share the same buffer for two different purposes? Just allocate 2 buffers; one for send and the other for recv. Then you don't need to deal with possibly problematic pointer math.
I'm assuming regexp_cmp(literalPt... treats lineralPt as a string: that string is not null terminated ( I can't see any code effort to terminate that string ) so the function simply overrun that buffer looking for the '\0' that never comes...