free() detecting heap corruption - c++

When using Visual Studio 2013 heap corruption is detected on calling free().
It is not detected on Linux.
My code seems to run fine until it hits the free function. I call free many times, but in one specific instance, it causes a window to pop up saying HEAP CORRUPTION DETECTED.
I've allocated memory to store pointers to strings(words) for two sets of words. For the first set of words, upon freeing them, no error message is given.
For the second set of words, upon freeing them, the error message pops up.
Here is the code for the first set of words, I made an array of words called arrayFictionary. The function takes a pointer to the array of pointers and adds on new words. No error message is given upon freeing(arrayFictionary).
void ConvertFictionary(char*** parrayFictionary, char* fictionary) {
char * pTemp = 0;
int32_t count = 1;
// put first fictionary word into an array
if(!(pTemp=strtok(fictionary, "\n"))) {//if the dictionary end is reached,
(*parrayFictionary)[count-1] = pTemp; // exit while loop
goto skipD;
}
*parrayFictionary = (char**) realloc(*parrayFictionary, (count + 1)*sizeof(char*));
(*parrayFictionary)[count-1] = pTemp;
count++;
while(1) {// put fictionary words into an array, exit when done
if(!(pTemp=strtok(NULL, "\n"))) {//if the dictionary end is reached,
(*parrayFictionary)[count-1] = pTemp; // exit while loop
break;
}
*parrayFictionary = (char**) realloc(*parrayFictionary, (count + 1)*sizeof(char*));
(*parrayFictionary)[count-1] = pTemp;
count++;
}
skipD:
return;
}
Here is the code for allocating an array for my second set of words called arrayFarticle. Same method is used with slight differences. Error message results upon calling free(arrayFarticle).
void ConvertFarticle(char*** parrayFarticle, char* farticle)
{
char * pTemp = 0;
int32_t count = 1;
// put first farticle word into an array
if(!(pTemp=strtok(farticle, "0123456789.,;: '\"\n!##$%%^&*()_-+=|\\[]{} <>?/~`’"))) //if the farticle end is reached, exit while loop
{
(*parrayFarticle)[count-1] = pTemp;
goto skipA;
}
if(strlen(pTemp)>=2)
{
*parrayFarticle = (char**) realloc(*parrayFarticle, sizeof(char*)*count + sizeof(char*)*2);
(*parrayFarticle)[count-1] = pTemp;
count++;
}
while(1) // put farticle words into an array, exit when done
{
if(!(pTemp=strtok(NULL, "0123456789.,;: '\"\n!##$%%^&*()_-+=|\\[]{}<>?/~`’"))) //if the farticle end is reached, exit while loop
{
(*parrayFarticle)[count-1] = pTemp;
break;
}
if(strlen(pTemp)>=2)
{
*parrayFarticle = (char**) realloc(*parrayFarticle, sizeof(char*)*count + 1);
(*parrayFarticle)[count-1] = pTemp;
count++;
}
}
skipA:
return;
}
I honestly don't know what's going on. I made sure that arrayFarticle isn't being written past its allocated limit.

Your last call to realloc results in *parrayFarticle pointing to a block with an odd (in the mathematical sense) size, and (quite likely) too small.

Related

Bad_alloc Exception in function in C++

Hi I am new in C++ programming, I have a function that return short*
My Function Code is
This function executes thousands of time because of this bad_alloc at memory location in generated so can anyone tell me how to solve this.
Code where getoneframe function call
short *myData = NULL;
sock.SetCameraIP(m_destination_IP, m_destination_port);
m_startCamFlag = sock.StartCamera();
if (!m_startCamFlag)
{
std::cout << "Unable to Start the Camera" << std::endl;
}
std::thread acquiringThread(callReceiveFunction, sock);
acquiringThread.detach();
while (flag)
{
myData = sock.GetOneFrame();
ImageShow(myData);
Sleep(15);
if (GetAsyncKeyState(VK_ESCAPE))
{
flag = false;
}
}
Your function allocates dynamic memory in the line
short *m_returnframeBuffer = new short[BYTE_PER_FRAME];
and returns the pointer to the calling function as
return m_returnframeBuffer;
It sounds like the calling function does not deallocate the memory, which causes bad_alloc to be thrown when the function is called thousands of times.
Make sure that the calling function deallocates the memory after it is done using it.
short* buffer = SomeCameraObject.GetOneFrame();
// Use buffer
// Deallocate memory.
delete [] buffer;
Update the while loop in the calling function to:
while (flag)
{
myData = sock.GetOneFrame();
ImageShow(myData);
Sleep(15);
if (GetAsyncKeyState(VK_ESCAPE))
{
flag = false;
}
// Add this line
delete [] myData;
}
while (m_bufferIndex1 != MAX_BYTE_PER_FRAME)
{
m_myChar1 = m_frameBuffer1[m_bufferIndex1++];
m_myChar2 = m_frameBuffer1[m_bufferIndex1++];
value = (m_myChar1 << 8) | m_myChar2;
m_returnframeBuffer[m_bufferIndex2++] = value;
}
m_bufferIndex1 is getting incremented twice. So, if m_bufferIndex1 is MAX_BYTE_PER_FRAME-1, it will enter the loop and gets incremented twice and the while loop never breaks. Add another check there before incrementing second time

Accessing a Dynamic Array causing a runtime error

I've been messing around with dynamic memory and I've hit a huge wall.
I'm trying to create a program where the user enters as many strings as they want, then can quit whenever, however after a second string is entered, the program crashes with out giving me any specific error message.
#include "stdafx.h"
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "new"
int _tmain(int argc, _TCHAR* argv[])
{
//Variables
int i=0,end=0,requiresSize=1;
char ** temp;
char item[256]="a";
char ** requires;
//Initialize each element in requiers
requires = new char * [requiresSize];
for(int j=0;j<requiresSize*2;j++){
requires[j]= new char[256];
}
while(strcmp(item,"q-")){
end=0;
printf("Enter h- for help.\nEnter q- to quit.\n");
printf("Please enter a string\n");
gets_s(item);
if(!strcmp(item,"h-")){
printf("Enter a string to add to the list.\nEnter p- to print the list.\n");
end=1;
}
if(!strcmp(item,"q-")){
break;
}
if(!strcmp(item,"p-")){
if(requires[0]!=NULL){
for(int j=0;j<requiresSize;j++){
printf("%d. %s\n",j,requires[j]);
}
}
end=1;
}
while(end==0){
printf("check1:i=%d\n",i);
//if search index is larger than size of the array,reallocate the array
if(i>= requiresSize){
temp = new char * [requiresSize*2];
//Initialize each element in temp
printf("check2:temp initalized\n");
for(int j=0;j<requiresSize*2;j++){
temp[j]= new char[256];
}
printf("check3:temp itmes initialized\n");
for(int j =0;j<requiresSize;j++){
//for each element in requires, copy that element to temp
temp[j]=requires[j];
}
printf("check4:copied requires into temp\n");
delete * requires;
requires = temp;
printf("check5:deleted requires and set requires equal to temp\n");
delete temp;
requiresSize = requiresSize *2;
}
printf("check6:\n");
//if the index at requires is not empty, check to see if it is the same as given item
if(requires[i]!= NULL){
printf("check8:index at requires is not empty\n");
//I know the error occurs here, something to do with accessing requires[i]
if(!strcmp( item, requires[i])){
printf("check9:index at requires is the same as item\n");
//if they are the same, break out of the loop, item is already included
break;
}else{
printf("check10:index at requires is different\n");
//otherwise, increase the index and check again (continue loop)
i++;
break;
}
}else{
printf("check11:index at requires is null, item added\n");
//if the index is empty, add the item to the list and break out of loop
requires[i]= item;
break;
}
printf("check7\n");
}
}
delete requires;
return 0;
}
Thank you in advance.
You need to realize that an assignment statement such as temp = requires (in this case) is only copying over the pointer, so that temp is now pointing to the same location in memory as requires; it does NOT copy over that memory.
This is leading to two problems:
You are allocating new 256-char arrays to each element of temp, and then reassigning each char* in temp to point to a different location, leaking all of that memory; there is now no way to reference the newly-allocated memory, and thus no way for you to free it.
You are assigning the pointer temp to requires, which, again, just means the two are now pointed to the same location in memory, and then deleting temp, which frees that memory (that, again, requires is also now pointing to).
Also, if you use new[] to allocate an array, you must use delete[] to free it. So requires = new char * [requiresSize]; requires you to use delete [] requires; at the end of the program, instead of just delete requires;. Same for each 256-char element of requires.
So, replace temp[j]=requires[j]; with an appropriate call to strcpy (or strncpy). And do not delete temp; the delete [] requires; at the end will handle that, since it is now pointing to that bit of memory.

Double Free or Corruption error when re-sizing Priority Queue

I've run into this error before, but the circumstances baffle me as I have run nearly this exact set of functions without having this issue.
Let me break it down:
The error is being caused by the resize() private member function of a custom priority queue I am working on. It is all centered around de-allocating the pointer to the old queue array. Before I explain any further, let me list the handful of relatively small functions I've isolated the problem to.
void unfairQ::enqueue(int val)
{
if (isFull())
resize();
numElements++;
ageCount++;
heapArr[numElements].data = val;
heapArr[numElements].age = 1;
heapArr[numElements].priority = heapArr[numElements].data;
heapifyUp(numElements);
if (ageCount == 100) {
heapSort();
ageCount = 0;
}
return;
}
bool unfairQ::isFull()
{
return (numElements == capacity);
}
void unfairQ::resize()
{
int newCap = (capacity * 1.5);
queueNode *tempHeap = new queueNode[newCap];
for (int i = 1; i <= numElements; i++) {
tempHeap[i].data = heapArr[i].data;
tempHeap[i].age = heapArr[i].age;
tempHeap[i].priority = heapArr[i].priority;
}
// delete [] heapArr;
capacity = newCap;
heapArr = tempHeap;
return;
}
The commented out line in the resize function is the one causing problems. If I do delete the pointer to the array I get the "double free" error, however if I remove that line I get a "free(): invalid next size (normal):" if I enqueue enough values to require a second resize().
Please let me know if you need any more information or if I need to clarify anything.
You seem to be using your array with indexes starting from 1, c++ uses indexes starting from 0. This can cause a buffer overflow.
For example:
If capacity is currently 5 (so heapArray can have 5 entries) andnumElementsis currently 4, yourisFullwill returnfalse(correctly), however yourenqueuecode then incrementsnumElements(from 4 to 5) and attempts to write toheapArray[5]` which is out of bounds and may overwrite some other memory.
Solution: start your indexes from 0, e.g. in the enqueue function, increment numElements after you write the data heapArray[numElements]
I found the problem, while I was referencing/incrementing/decrementing all the indices correctly and calling the appropriate functions at the appropriate times, I was operating under the notion that I was working with indices 1-size, but in the constructor (something I hadn't glanced at for a while) I'd initialized numElements as 0 which broke the whole gosh darned thing.
Fixed that and now everything is hunky dory!
Thanks for the help guys.

passing integer array in thread function

I am working on multiple producer and Single consumer problem.I wanted to pass Thread like 1,2,3 in the thread function so that individual thread can be named based on these number.
But the program is crashing after count 7 while creating thread.I think problem is due to
variable nThreadNo;
if i limit the count less than 7 it works fine.but if i make count more than this it crashes.
void CEvent1Dlg::CreateProducerThreads()
{
try
{
nThreadNo = new int20];
memset(nThreadNo,0,20);
if (nThreadNo ==NULL) return;
}catch(...)
{
MessageBox(_T("Memory allocation Failed"),_T("Thread"),1);
return ;
}
int i = 0;
for ( i = 0;i<20;i++)
{
//nThreadNo = i+1;
nThreadNo[i] = i+1;
hWndProducer[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ProducerThrdFunc,(void*)(nThreadNo+i),0,&dwProducerThreadID[i]);
if (hWndProducer[i] == NULL)
{
//ErrorHandler(TEXT("CreateThread"));
ExitProcess(3);
}
}
//WaitForMultipleObjects(20,hWndProducer,TRUE,INFINITE);
}
DWORD WINAPI ProducerThrdFunc ( LPVOID n )
{
int *nThreadNo = (int*)n;
char chThreadNo[33];
memset(chThreadNo,0,33);
while(1)
{
itoa(*nThreadNo,chThreadNo,10);
char* pMsg1 = new char[100];
char* pMsg2 = new char[100];
memset(pMsg1,0,100);
memset(pMsg2,0,100);
strcpy(pMsg1,"Producer ");
strcat(pMsg1," Thread No:");
strcat(pMsg1,chThreadNo);
if (stThreadInfoProd.pEventQueue->AddTail(pMsg1)==TRUE)
{
strcpy(pMsg2,"Producer ");
strcat(pMsg2," Thread No:");
strcat(pMsg2,chThreadNo);
strcat(pMsg2," Added the Msg");
}
else
{
strcpy(pMsg2,"Producer ");
strcat(pMsg2," Thread No:");
strcat(pMsg2,chThreadNo);
strcat(pMsg2,"failed to Add the Msg");
}
PostMessage(stThreadInfoProd.hWndHandle,UWM_ONUPDATEPRODUCERLIST,(WPARAM)pMsg2,0);
strcat(pMsg1," Adding Msg:");
//PostMessage(stThreadInfoProd.hWndHandle,UWM_ONUPDATEPRODUCERLIST,(WPARAM)pMsg2,0);
Sleep(3000);
}
return 0;
}
You are zeroing out the first 20 bytes of nThreadNo, not the first 20 * sizeof(int) bytes as you should be doing.
There are other arrays you are indexing into in this code: hWndProducer, dwProducerThreadID. Are there enough elements in those as well?
The CreateThread call is passing the integer value, but the thread function itself is treating it as a pointer to integer. Rather than this:
int *nThreadNo = (int*)n;
It should probably be:
int nThreadNo = (int)n;
Edit: I looked more closely at the call and I do see that it is passing an integer pointer. However, that value is stack data, which may not exist by the time the thread tries to read it. So it should probably just pass the integer value: (void*)(nThreadNo[i])
This line
if (nThreadNo ==NULL) return;
is worthless.
The new operator in modern C++ doesn't return NULL on failure, it throws a std::badalloc exception, but even if you were using an allocator that returns NULL to indicate failure, it's too late to detect it, you're already passed the NULL pointer to memcpy.

c++ stl priority queue insert bad_alloc exception

I am working on a query processor that reads in long lists of document id's from memory and looks for matching id's. When it finds one, it creates a DOC struct containing the docid (an int) and the document's rank (a double) and pushes it on to a priority queue. My problem is that when the word(s) searched for has a long list, when I try to push the DOC on to the queue, I get the following exception:
Unhandled exception at 0x7c812afb in QueryProcessor.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0012ee88..
When the word has a short list, it works fine. I tried pushing DOC's onto the queue in several places in my code, and they all work until a certain line; after that, I get the above error. I am completely at a loss as to what is wrong because the longest list read in is less than 1 MB and I free all memory that I allocate. Why should there suddenly be a bad_alloc exception when I try to push a DOC onto a queue that has a capacity to hold it (I used a vector with enough space reserved as the underlying data structure for the priority queue)?
I know that questions like this are almost impossible to answer without seeing all the code, but it's too long to post here. I'm putting as much as I can and am anxiously hoping that someone can give me an answer, because I am at my wits' end.
The NextGEQ function reads a list of compressed blocks of docids block by block. That is, if it sees that the lastdocid in the block (in a separate list) is larger than the docid passed in, it decompresses the block and searches until it finds the right one. Each list starts with metadata about the list with the lengths of each compressed chunk and the last docid in the chunk. data.iquery points to the beginning of the metadata; data.metapointer points to wherever in the metadata the function currently is; and data.blockpointer points to the beginning of the block of uncompressed docids, if there is one. If it sees that it was already decompressed, it just searches. Below, when I call the function the first time, it decompresses a block and finds the docid; the push onto the queue after that works. The second time, it doesn't even need to decompress; that is, no new memory is allocated, but after that time, pushing on to the queue gives a bad_alloc error.
Edit: I cleaned up my code some more so that it should compile. I also added in the OpenList() and NextGEQ functions, although the latter is long, because I think the problem is caused by a heap corruption somewhere in it. Thanks a lot!
struct DOC{
long int docid;
long double rank;
public:
DOC()
{
docid = 0;
rank = 0.0;
}
DOC(int num, double ranking)
{
docid = num;
rank = ranking;
}
bool operator>( const DOC & d ) const {
return rank > d.rank;
}
bool operator<( const DOC & d ) const {
return rank < d.rank;
}
};
struct listnode{
int* metapointer;
int* blockpointer;
int docposition;
int frequency;
int numberdocs;
int* iquery;
listnode* nextnode;
};
void QUERYMANAGER::SubmitQuery(char *query){
listnode* startlist;
vector<DOC> docvec;
docvec.reserve(20);
DOC doct;
//create a priority queue to use as a min-heap to store the documents and rankings;
priority_queue<DOC, vector<DOC>,std::greater<DOC>> q(docvec.begin(), docvec.end());
q.push(doct);
//do some processing here; startlist is a pointer to a listnode struct that starts the //linked list
//point the linked list start pointer to the node returned by the OpenList method
startlist = &OpenList(value);
listnode* minpointer;
q.push(doct);
//start by finding the first docid in the shortest list
int i = 0;
q.push(doct);
num = NextGEQ(0, *startlist);
q.push(doct);
while(num != -1)
{
q.push(doct);
//the is where the problem starts - every previous q.push(doct) works; the one after
//NextGEQ(num +1, *startlist) gives the bad_alloc error
num = NextGEQ(num + 1, *startlist);
//this is where the exception is thrown
q.push(doct);
}
}
//takes a word and returns a listnode struct with a pointer to the beginning of the list
//and metadata about the list
listnode QUERYMANAGER::OpenList(char* word)
{
long int numdocs;
//create a new node in the linked list and initialize its variables
listnode n;
n.iquery = cache -> GetiList(word, &numdocs);
n.docposition = 0;
n.frequency = 0;
n.numberdocs = numdocs;
//an int pointer to point to where in the metadata you are
n.metapointer = n.iquery;
n.nextnode = NULL;
//an int pointer to point to the uncompressed block of data, if there is one
n.blockpointer = NULL;
return n;
}
int QUERYMANAGER::NextGEQ(int value, listnode& data)
{
int lengthdocids;
int lengthfreqs;
int lengthpos;
int* temp;
int lastdocid;
lastdocid = *(data.metapointer + 2);
while(true)
{
//if it's not the first chunk in the list, the blockpointer will be pointing to the
//most recently opened block and docpos to the current position in the block
if( data.blockpointer && lastdocid >= value)
{
//if the last docid in the chunk is >= the docid we're looking for,
//go through the chunk to look for a match
//the last docid in the block is in lastdocid; keep going until you hit it
while(*(data.blockpointer + data.docposition) <= lastdocid)
{
//compare each docid with the docid passed in; if it's greater than or equal to it, return a pointer to the docid
if(*(data.blockpointer + data.docposition ) >= value)
{
//return the next greater than or equal docid
return *(data.blockpointer + data.docposition);
}
else
{
++data.docposition;
}
}
//read through the whole block; couldn't find matching docid; increment metapointer to the next block;
//free the block's memory
data.metapointer += 3;
lastdocid = *(data.metapointer + 3);
free(data.blockpointer);
data.blockpointer = NULL;
}
//reached the end of a block; check the metadata to find where the next block begins and ends and whether
//the last docid in the block is smaller or larger than the value being searched for
//first make sure that you haven't reached the end of the list
//if the last docid in the chunk is still smaller than the value passed in, move the metadata pointer
//to the beginning of the next chunk's metadata; read in the new metadata
while(true)
// while(*(metapointers[index]) != 0 )
{
if(lastdocid < value && *(data.metapointer) !=0)
{
data.metapointer += 3;
lastdocid = *(data.metapointer + 2);
}
else if(*(data.metapointer) == 0)
{
return -1;
}
else
//we must have hit a chunk whose lastdocid is >= value; read it in
{
//read in the metadata
//the length of the chunk of docid's is cumulative, so subtract the end of the last chunk
//from the end of this chunk to get the length
//find the end of the metadata
temp = data.metapointer;
while(*temp != 0)
{
temp += 3;
}
temp += 2;
//temp is now pointing to the beginning of the list of compressed data; use the location of metapointer
//to calculate where to start reading and how much to read
//if it's the first chunk in the list,the corresponding metapointer is pointing to the beginning of the query
//so the number of bytes of docid's is just the first integer in the metadata
if( data.metapointer == data.iquery)
{
lengthdocids = *data.metapointer;
}
else
{
//start reading from the offset of the end of the last chunk (saved in metapointers[index] - 3)
//plus 1 = the beginning of this chunk
lengthdocids = *(data.metapointer) - (*(data.metapointer - 3));
temp += (*(data.metapointer - 3)) / sizeof(int);
}
//allocate memory for an array of integers - the block of docid's uncompressed
int* docblock = (int*)malloc(lengthdocids * 5 );
//decompress docid's into the block of memory allocated
s9decompress((int*)temp, lengthdocids /4, (int*) docblock, true);
//set the blockpointer to point to the beginning of the block
//and docpositions[index] to 0
data.blockpointer = docblock;
data.docposition = 0;
break;
}
}
}
}
Thank you very much, bsg.
QUERYMANAGER::OpenList returns a listnode by value. In startlist = &OpenList(value); you then proceed to take the address of the temporary object that's returned. When the temporary goes away, you may be able to access the data for a time and then it's overwritten. Could you just declare a non-pointer listnode startlist on the stack and assign it the return value directly? Then remove the * in front of other uses and see if that fixes the problem.
Another thing you can try is replacing all pointers with smart pointers, specifically something like boost::shared_ptr<>, depending on how much code this really is and how much you're comfortable automating the task. Smart pointers aren't the answer to everything, but they're at least safer than raw pointers.
Assuming you have heap corruption and are not in fact exhausting memory, the commonest way a heap can get corrupted is by deleting (or freeing) the same pointer twice. You can quite easily find out if this is the issue by simply commenting out all your calls to delete (or free). This will cause your program to leak like a sieve, but if it doesn't actually crash you have probably identified the problem.
The other common cause cause of a corrupt heap is deleting (or freeing) a pointer that wasn't ever allocated on the heap. Differentiating between the two causes of corruption is not always easy, but your first priority should be to find out if corruption is actually the problem.
Note this approach won't work too well if the things you are deleting have destructors which if not called break the semantics of your program.
Thanks for all your help. You were right, Neil - I must have managed to corrupt my heap. I'm still not sure what was causing it, but when I changed the malloc(numdocids * 5) to malloc(256) it magically stopped crashing. I suppose I should have checked whether or not my mallocs were actually succeeding! Thanks again!
Bsg