realloc() issue,was not allocated - c++

I'm trying to read a string
char *string=malloc(sizeof(char));
char *start_string=string; //pointer to string start
while ((readch=read(file, buffer, 4000))!=0){ // read
filelen=filelen+readch; //string length
for (d=0;d<readch;d++)
*start_string++=buffer[d]; //append buffer to str
realloc(string, filelen); //realloc with new length
sometimes this crashes with the following error:
malloc: *** error for object 0x1001000e0: pointer being realloc'd was not allocated
but sometimes not, I have no idea how to fix it.

realloc() does not update the pointer passed in to it. If realloc() is successful the pointer passed in is free()d and the address of the allocated memory is returned. In the posted code realloc() will attempt to free(string) multiple times, which is undefined behaviour.
Store the result of realloc():
char* t = realloc(string, filelen);
if (t)
{
string = t;
}

The address of string may change when you call realloc().
char *string=malloc(sizeof(char));
char *start_string=string; //pointer to string start
while ((readch=read(file, buffer, 4000))!=0){ // read
filelen=filelen+readch; //string length
for (d=0;d<readch;d++)
*start_string++=buffer[d]; //append buffer to str
char* tempPtr = realloc(string, filelen); //realloc with new length
if( tempPtr ) string = tempPtr;
else printf( "out of memory" );
}

Related

How do I add space for a null char at the end of a character array?

Currently, my char array does not act like a C-string resulting in some bad memory, and which I'm assuming is to do with the fact that I don't have a null \0 at the end of it. I've been told I need to "allocate enough space" to do this, but I assumed that was what the "+1" at the end of my declaration of temp was for.
DNAStrand DNAStrand::operator+(const DNAStrand& other) const {
char* temp = new char [strlen(bases) + strlen(other) + 1];
strcat(temp, this->bases);
strcat(temp, other.bases);
return temp;
}
You have to initialize the temp after allocating memory. One simple way to do it while using new is add the parentheses. For plain old data POD it will initialize to 0.
char* temp = new char [strlen(bases) + strlen(other) + 1]();
If you do not initialize the temp could have garbage. e.g. if temp after allocation contains 'ab\0d456546 blah blah'. So the first strcat will assume ab as valid value and start appending after ab. It could have anything.

char pointer to string, then into array of strings. *** Error in `./a.out': malloc(): memory corruption: 0x0900c3b0 ***

I get this error:
* Error in `./a.out': malloc(): memory corruption: 0x0900c3b0 *
I am trying to convert a char pointer to a string, and then put that string into an array of strings for later use. I don't understand why this is not working. I am assuming that the string I put into the array gets deleted, and that might be the reason.
Error happens when I do new string(firstByte)
Here is the code:
char *entries[16] = {nullptr};
string *strEntries[16] = {nullptr};
char * firstByte = 0;
stringstream s;
size_t len;
string sfB;
firstByte = new char[sizeof(char)];
count = (FirstRootDirSec*512) + 32;
lseek(fd, count, SEEK_SET); //Takes us to 32 bytes after root directory, or first entry
//so either find a way to just read in one byte at a time, or
//take the first character of firstByte. firstbyte[0]. That's probably good.
for(int i = 0; i<16; i++){
//check first byte
//if first byte is a 41 or 40, then it is a long directory, and then we can jump ahead 32 bytes, or 0x20
lseek(fd, count, SEEK_SET); //Takes us to 32 bytes after
read(fd, firstByte, count);
count+=32;
if(firstByte[2] != '\0'){
//then not a long entry, and we can put it in entries.
// string str(firstByte);
//error happens when I do new string(firstByte)
**entries[i] = firstByte;
strEntries[i] = new string(firstByte);
cout<<entries[i]<<"blah"<<endl;**
}
}
You allocate an array large enough for a single byte:
firstByte = new char[sizeof(char)];
where sizeof(char) is a rather convoluted way of writing 1.
Then you try to read more than one byte into that an array:
read(fd, firstByte, count);
writing off the end of the array, and corrupting the heap.
It looks like count is the wrong number of bytes to read here, since you've just used the same variable to set where in the file to seek to. You need to figure out how many bytes you actually want to read each time, and make sure you have an array large enough for that.

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.

Why does this code leak?

Well, here again, this time the compiler is showing me a memory error (leak):
otest(18015,0xacae32c0) malloc: * error for object 0x194e734:
incorrect checksum for freed object - object was probably modified
after being freed.
* set a breakpoint in malloc_error_break to debug
I'm using clang with ARC activated and STL, this is a C++ file (.cpp).
What I found: If I comment the "delete" line it runs without problems. It makes me wonder who is freeing my allocated memory (cStr).
Btw. This code takes a query string (arg=abc&arg2=asdb) and returns a map whit those values.
static map<string, string> getDecodedQueryString( string qs ) {
map<string, string> r;
qs = qs+"&";
char key[100], value[100], * cStr, *ptr;
cStr = new char[ qs.length() ];
memcpy( cStr, qs.c_str(), url.length()-1);
cStr[qs.length()]=0;
ptr = strtok(cStr, "&");
while ( ptr != NULL && sscanf( ptr, "%[^=]=%[^&]", &key, &value ) == 2) {
r[key]=value;
ptr = strtok(NULL, "&");
}
delete [] cStr; //leaking?
return r;
}
Thanks
The problem is likely in these lines:
cStr = new char[ qs.length() ];
memcpy( cStr, qs.c_str(), url.length()-1);
cStr[qs.length()]=0;
Even without the memcpy() (which may have its own problems due to the length of url, as I mentioned above in a comment), the cStr[qs.length()] = 0 writes one byte past the end of the buffer.
If your compiler has strdup() available (it's nonstandard, but most do), you can replace this with:
cStr = strdup(qs.c_str());
// ...
free(cStr);
This saves you from having to mess around with manually allocating bytes, copying them, null terminating in the right place, etc.
Str = new char[ qs.length() ];
...
cStr[qs.length()]=0;
That write is invalid, it's one past the end of cStr. If the allocator stored a checksum right after the allocation, and checks it at delete time, you've just stomped on it.
Something along the lines of below will do the same thing.
std::stringstream ss(qs);
std::string temp;
std::string key;
std::string value;
while(std::getline(ss, temp, '&')) {
std::stringstream equal(temp);
std::getline(equal, key, '=');
std::getline(equal, value, '=');
r[key] = value;
}

How to convert a char* to a string?

When I convert char* to an string it gives an bad memory allocation error in 'new.cpp' . I used following method to convert char* called 'strData' and 'strOrg' to string.
const char* strData = dt.data();
int length2 = dt.length();
string s1(strData);
First time it work without any problem. But in the second convertion it gives above error. When I swap the two conversion in the order, it give the error always in the second conversion regardless of the char* I am converting. Whole code is shown in the following.
mysqlpp::Query query = conn.query("SELECT data,origin from image where id =2");
mysqlpp::UseQueryResult res = query.use();
mysqlpp::Row eee= res.fetch_row();
mysqlpp::Row::reference dt = eee.at(0);
mysqlpp::Row::reference org = eee.at(1);
const char* strData = dt.data();
int length2 = dt.length();
string s1(strData);
istringstream is1(s1);
char * imgData = new char;
is1.read(reinterpret_cast<char *> (imgData), length2);
delete [] strData;
const char* strOrg = org.data();
int length3 = org.length();
string s2(strOrg);
istringstream is2(s2);
char * imgOrg = new char;
is2.read(reinterpret_cast<char *> (imgOrg), length3);
delete [] strOrg;
This where the error comes from
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{ // report no memory
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
How can I solve this?
Instead of
char * imgData = new char;
is1.read(reinterpret_cast<char *> (imgData), length2);
try
char * imgData = new char[length2];
is1.read(reinterpret_cast<char *> (imgData), length2);
When you read data from an istringstream using read, the buffer you provide must have enough space to hold the results!
If you call new char; you get space for one char. Use new char[n]; to get space for n.
delete [] strData;
This is bad. The line above it probably is also but I know this one is.
You're deleting dt.data(). If I recall correctly this is guaranteed to be the internal buffer of the string.
This may or may not be your underlying problem, like I said, I suspect the line above it is bad also since you pass in a pointer to a single character to what would seem to expect a buffer of some length.
I believe the problem (or at least part of the problem) lies with your allocation:
char * imgData = new char;
This only allocates 1 char, and then istream.read will assume that imgData is a buffer of chars (notice plural) and place whatever it reads into the single char you allocated, and then beyond that into the memory used by who knows what.
The result is typically called "undefined behaviour" - sometimes you'll get away with it as in the first instance, other times you won't, as in the second conversion.