Writing heapify function from scratch, getting a "stack-based buffer overrun" - c++

I am trying to implement the heap sort algorithm for the first time, but I am getting an error with the heapify function.
Unhandled exception at 0x0005369A in heapify.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.
The console does open, and the output is 999 10 5 11 1012398875 2 0 1.
Could someone help me understand what is going wrong here? Thank you.
#include <iostream>
// given the address of element 0 of an array, and a non-zero index k, heapify assumes that the L/R subtrees
// of node k are max heaps. But the subtrees combined with node k do not necesarily form
// a max heap. heapify interchanges the value at node k with the value of one of its children,
// and then calls itself on the subtree in question
int heapify(int* n, int k, int sizeOfHeap)
{
// terminate the function if the input "node" is not actually a node
if (k > sizeOfHeap)
{
return 0;
}
int root = *(n + k); // value of kth node
int leftChild = *(n + 2 * k); // value of left chold
int rightChild = *(n + 2 * k + 1); // value of right child
if (root < leftChild)
{
// swap value of kth node with value of its left child
int temp = root;
*(n + k) = leftChild;
*(n + 2 * k) = root;
// call heapify on the left child
heapify(n, 2 * k, sizeOfHeap);
}
else
{
// swap value of kth node with value of its right child
int temp = root;
*(n + k) = rightChild;
*(n + 2 * k + 1) = root;
// call heapify on right child
heapify(n, 2 * k + 1, sizeOfHeap);
}
}
int main()
{
// arr is the array we will heapify. 999 is just a placeholder.
// The actual (almost) heap occupies indices 1 - 7
int arr[8] = {999, 3, 10, 11, 5, 2, 0, 1};
int sizeOfHeap = 8;
heapify(arr, 1, sizeOfHeap);
// print out arr
int i;
for (i = 0; i <= 7; i++)
{
std::cout << arr[i] << std::endl;
}
}

Unhandled exception at 0x0005369A in heapify.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.
The console does open, and the output is 999 10 5 11 1012398875 2 0 1.
Could someone help me understand what is going wrong here? Thank you.
Stack of process (one of real-live uses of stack data structure, FILO queue) is the place in memory for static allocation. Always small and mostly same size for all processes.
On stack, still, compiler save local variables i.e. small statically allocated buffers (this happens then the stack pointer is, on Linux, moved to expand the stack size, and compiler evaluate offsets on stack).
They (buffers) could not be handled correctly (unsafe lib functions, like strcpy()) so they could be potentially overflowed (overrunned) leading to buffer overflow vulnerability.
Stack cookie AKA stack canary is mitigation technique for writing sequential data on stack while attacker try to exploit vulnerability like stack buffer overflow, but not limited to (if You do stack pivot from heap back to heap but badly overwrite saved instruction pointer... nevermind ;) ).
If the overflow is detected then they raise SegFault.
Example link with example of exploitation.
This answers Your direct question (understand what is going wrong).
Now, You should debug it and then narrow down the issue. Especially ask the next question, not edit again.

Related

where is the faulty logic in this re-heap function?

I'm currently working with a heap structure which is suppose to be used to sort numbers in an array. I have done something like this in the code when I want to sort the structure when I pop(dequeue) a element from the heap.
template<typename T>
inline void dHeap<T>::reHeapDown(int root, int bottom)
{
int minChild;
int rightChild;
int leftChild;
int temp;
// Get index of root's right/left child
leftChild = root * 2 + 1;
rightChild = root * 2 + 2;
//Then we are not done with re-heaping
if (leftChild <= bottom)
{
if (leftChild == bottom)
{
minChild = leftChild;
}
else
{
if (arr[leftChild] <= arr[rightChild])
minChild = leftChild;
else
minChild = rightChild;
}
if (arr[root] > arr[minChild])
{
// Swap these two elements
temp = arr[root];
arr[root] = arr[minChild];
arr[minChild] = temp;
// Make recursive call till reheaping completed
reHeapDown(minChild, bottom);
}
}
}
My thought here is that the lowest value in the heap always will be in the root and that's the value that I will be poped(dequeued) in my pop function.
But I'm having some problem that it wont sort the heap correctly.
is there something wrong with my logic in this function and if so, where is it?
Building a heap only enforces the property:
in case of min heap every parent is lesser than it children
in case of max heap every parent is greater than its children.
in case of min-max heap even depth levels (0,2,4..) are lesserr and odd levels (1,3,5...) are greater than their respective children.
However the heap will not necessarily be sorted. It will be balanced, because it is filled in order, level by level, from left to right.
Heapsort will sort an array by using heap functions. The final array will also work as a balanced and sorted heap.

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.

Stack overflow in my recursive function, is it due to logic or large number?

When I run my function on a small array, it works fine. However when I use a large array, I keep getting stack overflow.
Is it due to my incorrect logic in my code? or is it just taking a long time?
void RecursiveSort(T data[], int first, B last)
{
// Sorts the array elements a[first] through a[last] recursively.
// base case is if first and last are the same, which means we
// have no subarrays left to do
if (first < last)
{
int minIndex = first;
// replace first index of array with smallest of values in the array
for (int index = first+1; index < last; index++)
{
if (data[index] < data[minIndex])
// swap values
minIndex = index;
}
int temp = data[first];
data[first] = data[minIndex];
data[minIndex] = temp;
RecursiveSort(data, first + 1, last);
}
}
You see stack overflow error just because your stack has a limited size. Each time you call your recursive function you use some amount of memory for storing some values, such as an address to return to, values of the function parameters, etc.—see this Wikipedia article for more information.
As a rule of thumb, if your recursion goes more than 1000 levels deep, you may be in trouble.
The good news is that your code is an example of a tail recursion, where the recursive call is the last statement in the function. Such functions can be easily converted to a loop:
for (first = 0; first < last; ++first) {
...
}
Or, if you really need to create a recursive sort, don't try to implement a selection sort, but look at the Quicksort or merge sort, both can be implemented using recursion.
Your program has a limited stack memory. How big this memory is might depend on your compiler or your OS.
For each call to your recursuve function all arguments to the function are placed on the stack. This means that each call will take another chunk of size (last - first)*sizeof(T).
With a large array (last - first) will be bigger, but it also means that your recursive function will be called more times.
In total you will need approximately (last - first)*(last - first)*sizeof(T)/2 + (last - first)*2*sizeof(int) of stack size. Looking at that formula you can see how your stack gets in trouble when the size of the array increases.
Yes,
I also agree that you will be having limited stack memory, but you can reduce Recursion calls by putting a SWAP flag as mentioned below.
void recursive_bubble_sort(int *array, int size)
{
bool swap = false; // to avoid recursion call when no swapping is required
for(int i=0; i+1 < size; ++i)
{
if(array[i] < array[i+1])
{
int tmp = array[i];
array[i] = array[i+1];
array[i+1] = tmp;
swap = true;
}
}
if(swap)
recursive_bubble_sort(array, size);
}
Or implement Quicksort or Merge sort with recursion to cut down your stack.

Simple heap program- what does this variable do

void ReheapDown( int* heap, int top, int swpIndx, int numElements ) {
int leftChild = 2 * top + 1;
int rightChild = 2 * top + 2;
int minChild;
if (leftChild < numElements) {
// find subscript of smallest child
if (rightChild >= swpIndx || heap[leftChild] < heap[rightChild])
minChild = leftChild;
else
minChild = rightChild;
// if data at top is greater than smallest
// child then swap and continue
if (heap[top] > heap[minChild]) {
swap( heap[top], heap[minChild] );
ReheapDown( heap, minChild, swpIndx, numElements );
}
}
This is for a simple heap. ReheapDown is used partly for removing items in the heap. What does swpIndx do though? (I need to know to do a homework assignment, where I'm supposed to write the function that removes a certain key in the heap.)
To remove a key from a heap, we might want to swap it with the last key in the heap before deleting it, otherwise there would be a gaping hole in the heap.
However, swapping the last node with the node we want to remove can upset the ordering of the heap, which is where that ReheapDown method that you provided comes in.
I believe the swpIndex parameter is the index into which we have placed the element that we wish to remove. So that part of the code basically says:
if (there exists a left child) {
if (there is no right child || left child < right child)
minChild <- left child
else
minChild <- right child
}
I think that parameter is unnecessary though, since it seems that it's only purpose is to check for the existence of the left and right child; this can also be accomplished by comparing the leftChild and rightChild indices to numElements.
Hope this helps :)

Stack and queue operations on the same array

I've been thinking about a program logic, but I cannot draw a conclusion to my problem.
Here, I've implemented stack and queue operations to a fixed array.
int A[1000];
int size=1000;
int top;
int front;
int rear;
bool StackIsEmpty()
{
return (top==0);
}
bool StackPush( int x )
{
if ( top >= size ) return false;
A[top++] = x;
return true;
}
int StackTop( )
{
return A[top-1];
}
bool StackPop()
{
if ( top <= 0 ) return false;
A[--top] = 0;
return true;
}
bool QueueIsEmpty()
{
return (front==rear);
}
bool QueuePush( int x )
{
if ( rear >= size ) return false;
A[rear++] = x;
return true;
}
int QueueFront( )
{
return A[front];
}
bool QueuePop()
{
if ( front >= rear ) return false;
A[front++] = 0;
return true;
}
It is presumed(or obvious) that the bottom of the stack and the front of the queue is pointing at the same location, and vice versa(top of the stack points the same location as rear of the queue).
For example, integer 1 and 2 is inside an array in order of writing. And if I call StackPop(), the integer 2 will be popped out, and if I call QueuePop(), the integer 1 will be popped out.
My problem is that I don't know what happens if I do both stack and queue operations on the same array. The example above is easy to work out, because there are only two values involved. But what if there are more than 2 values involved?
For example, if I call
StackPush(1);
QueuePush(2);
QueuePush(4);
StackPop();
StackPush(5);
QueuePop();
what values will be returned in the order of bottom(front) from the final array?
I know that if I code a program, I would receive a quick answer. But the reason I'm asking this is because I want to hear a logical explanations from a human being, not a computer.
ADDED:
For the second example, I have 4 candidates.
25
12
24
45
or no answer from here at all.
Why are you implementing these on the same array? The elements of one structure might overwrite those from the other if you do it like this.
You essentially have (something resembling) a deque there however, but it's difficult to run your program by hand because you have different pointers for the two data structures but only one array for both of them.
It is presumed(or obvious) that the bottom of the stack and the front of the queue is pointing at the same location, and vice versa(top of the stack points the same location as rear of the queue).
Well, ok in this case, but you should just use a Deque, which doesn't work on this assumption. Or use different vectors for the queue and stack.
Generally a human does this is just how a computer does it. Just have your program print the contents of A after each operation, and it should be logical enough.
In the case of your code, it will probably not do what you expect since the stack routines and the queue routines maintain different variables for where to push to.
StackPush(1); // place 1 at position 0; increase top of stack to 1
QueuePush(2); // place 2 at position 0; increase rear of queue to 1
QueuePush(4); // place 4 at position 1; increase rear of queue to 2
StackPop(); // get value(2) from position 0; decrease top of stack to 0
StackPush(5); // place 5 at position 0; increase top of stack to 1
QueuePop(); // get value(5) from position 0; increase front of queue to 1
If you instead wrote the code so that the stack use rear instead of top, then you would see these results.
StackPush(1); // place 1 at position 0; increase rear to 1
QueuePush(2); // place 2 at position 1; increase rear to 2
QueuePush(4); // place 4 at position 2; increase rear to 3
StackPop(); // get value(4) from position 2; decrease rear to 2
StackPush(5); // place 5 at position 2; increase rear to 3
QueuePop(); // get value(1) from position 0; increase front to 1
I'm not sure exactly what problem you're trying to solve, but this looks very much like a double-ended queue. Depending on the problem you're trying to solve, a circular buffer may be worth examining.
Have a look at those proven data structures to at least give yourself more context for implementing your own data structure, and hopefully one of them is what you're after.
the result will be 4 and 1, because the array has 1 2 4 and when you say stack pop it gets the recently added item which is 4. and when after the stack push 5 the array will be 1 2 5 and then when you pop from the queue you will get 1 as queue pop gets the first added item.