free(): invalid pointer when adding string - c++

This code works ok:
void sendToOne(int fd, string message)
{
message += "$";
char* S = new char[message.length()];
strcpy(S, message.c_str());
write(fd, S, message.length());
}
But when I add small change:
void sendToOne(int fd, string message)
{
string msg2 = message + "$";
char* S = new char[msg2.length()];
strcpy(S, msg2.c_str());
write(fd, S, msg2.length());
}
I am getting: free(): invalid pointer error. Can you explain me why does that happen?

Your code has a buffer overrun write in it:
char* S = new char[msg2.length()];
strcpy(S, msg2.c_str());
The first line allocates enough space for the characters in msg2, but the second line copies said characters (assuming no embedded NULs) and the NUL byte at the end (a total of one byte more than you allocated). If you get unlucky, and there were no slack bytes at the end of the allocation, you'll often overwrite allocator metadata bytes preceding a subsequent allocation (or an entry in the free list); when the allocator tries to use them, it (if you're "lucky") tries to read invalid memory and dies immediately; if you're "unlucky", it happens to point to random memory that's available to your process, but probably not the right place, and you get progressively more and more corruption until everything explodes.
All that said, it's kind of silly to do this. Just write the string's data directly:
string msg2 = message + "$";
write(fd, msg2.c_str(), msg2.length());
which also avoids the memory leak you made by using new without smart pointer management or a matching call to delete[].

you need extra 1 byte to hold the null character
char* S = new char[msg2.length() + 1];
see strcpy

Related

Memory Leak (char[])

When I run my program, it can run for a while, then all of the sudden, it experiences a huge memory leak. I traced it out using a snapshot of the heap when it crashed, and I have a mysterious char[] with the size of 232,023,801 Bytes. The minutes preceding crash have no unusual behavior until then. The only places where I use char arrays is in the following piece of code:
string ReadString(DWORD64 addr) {
char* buffer = new char[128];
bool validChar = true;
for (int c = 0; c < 128 && validChar; c++) {
buffer[c] = Mem.Read<char>(addr+ (0x1 * c), sizeof(char));
if (!isalnum(buffer[c]) && !ispunct(buffer[c]))
validChar = false;
}
string ret= string(buffer);
delete[] buffer;
return ret;
}
All this code should be doing is reading a few characters from memory, saving the char array to a string, cleaning up the array, and returning the string. How is the memory leak originating from here? Or does the char[] in the heap snapshot potentially point to another issue?
Assuming that string here is std::string:
You call string(buffer) which assumes that buffer is 0-terminated and allocates a new string. But your code doesn't ensure that buffer is actually 0-terminated, so this can cause undefined behavior, including potentially crashing or allocating too much memory for the string.
You probably want to use the string(buffer, size) constructor instead, which doesn't require buffer to be 0-terminated.
I'd also recommend avoiding the manual new/delete. One way to do this is to create an empty string and push_back the characters you read to it. This avoid the need for buffer.

c++: Does the new operator for dynamic allocation check for memory safety?

My question arises from one of my c++ exercises (from Programming Abstraction in C++, 2012 version, Exercise 12.2). Here it is:
void strcpy(char *dst, char *src) {
while (*dst++ = *src++);
}
The definition of strcpy is dangerous. The danger stems from the fact
that strcpy fails to check that there is sufficient space in the
character array that receives the copy, thereby increasing the chance
of a buffer-overflow error. It is possible, however, to eliminate much
of the danger by using dynamic allocation to create memory space for
the copied string. Write a function
char *copyCString(char *str);
that allocates enough memory for the C-style string str and then
copies the characters—along with the terminating null character—into
the newly allocated memory.
Here's my question:
Is this new method really safe? Why it's safe?
I mean, to be a little bit radical, what if there isn't enough space in the heap?
Is the new operator able to check for space availability and fall in an elegant way if there isn't enough space?
Will that cause other kind of "something-overflow"?
If new fails to allocate the requested memory, it's supposed to throw a std::bad_alloc exception (but see below for more). After that, the stack will be unwound to the matching exception handler, and it'll be up to your code to figure out what to do from there.
If you really want/need to assure against an exception being thrown, there is a nothrow version of new you can use that will return a null pointer to signal failure--but this is included almost exclusively for C compatibility, and not frequently used (or useful).
For the type of situation cited in the question, you normally want to use std::string instead of messing with allocating space yourself at all.
Also note that on many modern systems, the notion of new either throwing or returning a null pointer in case of failure, is really fairly foreign. In reality, Windows will normally attempt to expand the paging file to meet your request. Linux has an "OOMKiller" process that will attempt to find "bad" processes and kill them to free up memory if you run out.
As such, even though the C++ standard (and the C standard) prescribe what should happen if allocation fails, that's rarely what happens in real life.
New operator will throw bad_alloc exception if it cannot alocate memory, unless nothrow specified. If you specify constant nothrow you will get NULL pointer back if it cannot alocate memory.
The code for strcpy is unsafe because it will try copying outside of the allocated memory for the dst pointer. Example:
int main()
{
const char* s1 = "hello"; // allocated space for 6 characters
char* s2 = new char[ 2 ]; // allocated space for 2 characters.
strcpy( s2, s1 );
cout << s2 << endl;
char c; cin >> c;
return 0;
}
This prints the correct value "hello", but remember that the pointer s2 was allocated to only have space for 2 characters. So we can assume that the other characters were written to the subsequent memory slots, which is unsafe as we could be overwriting data or accessing invalid memory.
Consider this solution:
char* e4_strdup( const char*& c )
{
// holds the number of space required for the c-string
unsigned int sz{ 0 };
// since c-style strings are terminated by the '\0' character,
// increase the required space until we've found a '\0' character.
for ( const char* p_to_c = c; *p_to_c != '\0'; ++p_to_c )
++sz;
// allocate correct amount of space for copy.
// we do ++sz during allocation because we must provide enough space for the '\0' character.
char* c_copy{ new char[ ++sz ] }; // extra space for '\0' character.
for ( unsigned int i{ 0 }; i < sz; ++i )
c_copy[ i ] = c[ i ]; // copy every character onto allocated memory
return c_copy;
}
The new operator will still return a std::bad_alloc exception if you run out of memory.

Seg faulting on a car cast from unsigned char to const char in C++

Code:
const char* copyoutmsg(unsigned char instring[2055])
{
char* msg = "";
const char* wholestring = reinterpret_cast<const char*>(instring);
strncpy(msg,wholestring,eotpos-5);
printf("Message: %s\n",msg);
return msg;
}
It's seg faulting (process returning 139) - can't get my head round it. Eotpos is the position of the end of the message. What this function is meant to do is input an unsigned char array, convert it to const char and return the message minus 5 chars from the end. I cannot see what is causing this.
Ignoring all other problems in your code, segfault source is in these statements:
char* msg = "";
const char* wholestring = reinterpret_cast<const char*>(instring);
strncpy(msg,wholestring,eotpos-5);
You're trying to copy the string pointed by wholestring into a memory location where msg is pointing to. msg is pointing in the read-only part of the memory, where the string literals are stored (see the first statement of your code). You need to allocate memory for the message first:
char* msg = new char[eotpos - 5 + 1];
const char* wholestring = reinterpret_cast<const char*>(instring);
strncpy(msg,wholestring,eotpos-5);
Don't forget to delete memory afterwards!
Note that you cannot initialize a char* from a string literal in C++11. The clause which allowed that initialization in C++98 and C++03 was removed. If you worked out why that is, you have a hint on one thing which went wrong! You may want to read up on memory allocation as well or, better yet, use proper C++ facilities like std::string as raw pointer manipulators are fairly hard to get right.
I might be wrong, but you don't allocate any memory for msg, of course it will segfault if you try to copy a string to it.
Besides, if eotpos is the position of the last message character (and it does not point to the string termination literal), the message has the length of eotpos+1 (without the string termination literal), since the counting starts with 0. That is why you will have to allocate eotpos+1-5+1 characters for msg (the last +1 is being used for the string termination literal).
Initialize msg like this:
char* msg = malloc(eotpos-3); // Or new char[eotpos - 3], when I answered, there was still just the C tag
msg[eotpos-4] = 0;
And then copy:
strncpy(msg,wholestring,eotpos-4);
Well, depending on what eotpos really is, you have to fix the constant values above. But in my opinion, your description is a little value.

Memcpy, string and terminator

I have to write a function that fills a char* buffer for an assigned length with the content of a string. If the string is too long, I just have to cut it. The buffer is not allocated by me but by the user of my function. I tried something like this:
int writebuff(char* buffer, int length){
string text="123456789012345";
memcpy(buffer, text.c_str(),length);
//buffer[length]='\0';
return 1;
}
int main(){
char* buffer = new char[10];
writebuff(buffer,10);
cout << "After: "<<buffer<<endl;
}
my question is about the terminator: should it be there or not? This function is used in a much wider code and sometimes it seems I get problems with strange characters when the string needs to be cut.
Any hints on the correct procedure to follow?
A C-style string must be terminated with a zero character '\0'.
In addition you have another problem with your code - it may try to copy from beyond the end of your source string. This is classic undefined behavior. It may look like it works, until the one time that the string is allocated at the end of a heap memory block and the copy goes off into a protected area of memory and fails spectacularly. You should copy only until the minimum of the length of the buffer or the length of the string.
P.S. For completeness here's a good version of your function. Thanks to Naveen for pointing out the off-by-one error in your terminating null. I've taken the liberty of using your return value to indicate the length of the returned string, or the number of characters required if the length passed in was <= 0.
int writebuff(char* buffer, int length)
{
string text="123456789012345";
if (length <= 0)
return text.size();
if (text.size() < length)
{
memcpy(buffer, text.c_str(), text.size()+1);
return text.size();
}
memcpy(buffer, text.c_str(), length-1);
buffer[length-1]='\0';
return length-1;
}
If you want to treat the buffer as a string you should NULL terminate it. For this you need to copy length-1 characters using memcpy and set the length-1 character as \0.
it seems you are using C++ - given that, the simplest approach is (assuming that NUL termination is required by the interface spec)
int writebuff(char* buffer, int length)
{
string text = "123456789012345";
std::fill_n(buffer, length, 0); // reset the entire buffer
// use the built-in copy method from std::string, it will decide what's best.
text.copy(buffer, length);
// only over-write the last character if source is greater than length
if (length < text.size())
buffer[length-1] = 0;
return 1; // eh?
}
char * Buffers must be null terminated unless you are explicitly passing out the length with it everywhere and saying so that the buffer is not null terminated.
Whether or not you should terminate the string with a \0 depends on the specification of your writebuff function. If what you have in buffer should be a valid C-style string after calling your function, you should terminate it with a \0.
Note, though, that c_str() will terminate with a \0 for you, so you could use text.size() + 1 as the size of the source string. Also note that if length is larger than the size of the string, you will copy further than what text provides with your current code (you can use min(length - 2, text.size() + 1/*trailing \0*/) to prevent that, and set buffer[length - 1] = 0 to cap it off).
The buffer allocated in main is leaked, btw
my question is about the terminator: should it be there or not?
Yes. It should be there. Otherwise how would you later know where the string ends? And how would cout would know? It would keep printing garbage till it encounters a garbage whose value happens to be \0. Your program might even crash.
As a sidenote, your program is leaking memory. It doesn't free the memory it allocates. But since you're exiting from the main(), it doesn't matter much; after all once the program ends, all the memory would go back to the OS, whether you deallocate it or not. But its good practice in general, if you don't forget deallocating memory (or any other resource ) yourself.
I agree with Necrolis that strncpy is the way to go, but it will not get the null terminator if the string is too long. You had the right idea in putting an explicit terminator, but as written your code puts it one past the end. (This is in C, since you seemed to be doing more C than C++?)
int writebuff(char* buffer, int length){
char* text="123456789012345";
strncpy(buffer, text, length);
buffer[length-1]='\0';
return 1;
}
It should most defiantly be there*, this prevents strings that are too long for the buffer from filling it completely and causing an overflow later on when its accessed. though imo, strncpy should be used instead of memcpy, but you'll still have to null terminate it. (also your example leaks memory).
*if you're ever in doubt, go the safest route!
First, I don't know whether writerbuff should terminate the string or not. That is a design question, to be answered by the person who decided that writebuff should exist at all.
Second, taking your specific example as a whole, there are two problems. One is that you pass an unterminated string to operator<<(ostream, char*). Second is the commented-out line writes beyond the end of the indicated buffer. Both of these invoke undefined behavior.
(Third is a design flaw -- can you know that length is always less than the length of text?)
Try this:
int writebuff(char* buffer, int length){
string text="123456789012345";
memcpy(buffer, text.c_str(),length);
buffer[length-1]='\0';
return 1;
}
int main(){
char* buffer = new char[10];
writebuff(buffer,10);
cout << "After: "<<buffer<<endl;
}
In main(), you should delete the buffer you allocated with new., or allocate it statically (char buf[10]). Yes, it's only 10 bytes, and yes, it's a memory "pool," not a leak, since it's a one-time allocations, and yes, you need that memory around for the entire running time of the program. But it's still a good habit to be into.
In C/C++ the general contract with character buffers is that they be null-terminiated, so I would include it unless I had been explicitly told not to do it. And if I did, I would comment it, and maybe even use a typedef or name on the char * parameter indicating that the result is a string that is not null terminated.

Heap corruption when deleting a string

Here is my code:
std::string readString()
{
int strLen = Read<int>();
char* rawString = new char[strLen];
Read(rawString, strLen);
rawString[strLen] = '\0';
std::string retVal(rawString);
delete [] rawString;
return retVal;
}
The first line reads the length of the string.
The second line creates a new char array (c-string) with the string length
The third line reads the string (its reading it from a file)
The 4th line adds a NULL to the end.
The 5th line creates an std::string out of the c-string.
The 6th line deletes the c-string (HEAP CORRUPTION HAPPENS HERE)
The 7th line returns the string, but it never reaches this point because of an error.
On the 6th line I get a heap corruption error:
CRT detected that the application wrote to memory after end of heap buffer.
My question may be obvious, but why am I getting a heap corruption? When I create an std::string, it should copy the string, and I should be safe to delete the c-string.
Currently, I'm suspecting that std::string is trying to access the c-string after I delete it.
Any ideas?
You're accessing past the reserved bytes for your string. You reserved strLen characters, but put a \0 at the character strLen. Counting as C arrays from 0, character strLen is at position strLen + 1, so you're putting a value outside the reserved space for the string. You should reserve strLen + 1 in the second line of your main for your code to work.
Change:
char* rawString = new char[strLen];
to:
char* rawString = new char[strLen + 1];
int strLen = Read<int>() probably only returns the length of a non-null-terminated string, and when you try to write the \0 byte to the string, you run into buffer overflow problems.
You should check what strLen is, and most likely you either have to allocate like this:
char *rawString = new char[strlen+1];
Or use the overloaded constructor of std::string(const char *, size_t n) like this:
std::string retVal(rawString, strlen);
Since arrays are 0-indexed in c++, when you create an array of size strLen and then place a 0 at position strLen, you are writing that zero one after the end of the array you allocated.
Many advices so far, but none which address the exception safety issue: how do you get rid of that potential memory leak ?
There are two ways to avoid allocating with new (and thus facing a memory leak). The first is extremely simply and makes use of a compiler extension known as VLA for Variable Length Array:
std::string readString()
{
int strLen = Read<int>();
char rawString[strLen+1]; // VLA: the length is determined at runtime
// but the array is nonetheless on the stack
Read(rawString, strLen);
rawString[strLen] = '\0';
std::string retVal(rawString);
return retVal;
}
The other is compliant with the standard: string has an internal buffer which you can access (thanks to GMan, data is not the right access method)
std::string readString()
{
int strLen = Read<int>();
std::string retVal(strLen, '\0'); // no need to allocate extra space
Read(&retVal[0], strLen); // &retVal[0] gives access to the buffer
return retVal;
}
I do believe that the last version is MUCH better. There is no longer any copying involved :)
rawString[strLen] = '\0';
Writes the NUL off the end of the space you have allocated.
If strLen is 10, then you allocate space for 10 characters, read 10 characters, and write this NUL in position 11. Ooops