stl map, set error: memory clobbered past end of allocated block - c++

As I tried to solve this interview problem: find the sum of continuous element in an array which equals to a target number, so I come up with the following code. However, I really don't understand why it has some memory allocation problem. Here is the link to the full code. when I tried to insert the second element of currSum into the set and map, it will have some error message like "memory clobbered past end of allocated block". Isn't set, map dynamically allocated for insert? I really don't understand why it's not working as I think.
I also paste the full code here:
#include <map>
#include <set>
#include <iostream>
using namespace std;
void print_array(int arr[], int start, int end)
{
for(int i=start;i<=end;i++)
cout<<arr[i]<<" ";
cout<<endl;
}
//given an array, find the continous sum of the array which is a target number
void findTargetSum(int arr[], int target, int sizeArr)
{
map<int, int> valIdxMap;
set<int> prevSet;
int* currSum= new int(sizeArr+1);
currSum[0]=0;
for(int i=1;i<=sizeArr;i++)
{
currSum[i]=currSum[i-1]+arr[i-1];
}
//now the problem is to find two elements i, j in array currSum,where currSum[j]-currSum[i]=target && j>i
for(int i=0; i<=sizeArr;i++)
{
int tmp=currSum[i]-target;
set<int>::iterator iter=prevSet.find(tmp);
if (iter !=prevSet.end())
{
cout<<"located one range of array elements with sum to"<<target<<endl;
int startIdx=valIdxMap[*iter];
print_array(arr,startIdx,i-1);
}
else
{
prevSet.insert(currSum[i]);
valIdxMap.insert(make_pair(currSum[i],i));
}
}
delete currSum;
}
void testfindTargetSum()
{
int tst_arr[]={2,4,5,-1,3,8};
int target=11;
findTargetSum(tst_arr,11,6);
}
int main()
{
testfindTargetSum();
return 1;
}

The error is in this line:
int* currSum= new int(sizeArr+1);
That line acquires a single int and initializes it to the value sizeArr+1. You probably meant:
int* currSum= new int[sizeArr+1];
That will acquire a block of sizeArr+1 elements of type int. Additionally you will have to change the line delete currSum; to be delete [] currSum;.
My advice, on the other hand, would be not to manage memory manually but use a standard container, for example:
std::vector<int> currSum( sizeArr+1 );
Will basically be an in-place replacement for your current implementation and it will manage memory automatically.
As of the implementation, I believe that you can actually do it without any extra memory in O(N) by accumulating the start index, end index and sum of the values in three variables while iterating. While the accumulated value is smaller than the target, increment the end index and add the value. When the accumulated value grows higher than the target, increment the start index and decrement the accumulated value by that amount.

you wrote
int* currSum= new int(sizeArr+1);
you probably meant
int* currSum= new int[sizeArr+1];

Related

C++: Insert an element in a Vector without insert()

I have been trying to solve the above problem for a friend, everytime the last element of the vector gets removed although I feel that its size should increase dynamically after insertion.
Here's the Code:
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
void display(vector<int> arr){
cout<<"Result"<<endl;
for(auto &p: arr){
cout<<p<<endl;
}
}
void indsert(vector<int> arr, int size, int element, int ind){
for(int i=size+1; i>=ind; i--)
arr[i] = arr[i-1];
arr[ind] = element;
display(arr);
}
int main()
{
int ind,size,element;
cout<<"Enter the size of the array"<<endl;
cin>>size;
vector<int> arr;
cout<<"Enter the elements of the array"<<endl;
for(int i=0;i<size;i++){
int temp;
cin>> temp;
arr.push_back(temp);
}
cout<<"Enter the element to be inserted"<<endl;
cin>>element;
cout<<"Enter the index"<<endl;
cin>>ind;
indsert(arr, size, element, ind);
return 0;
}
You have two problems.
The first is with the function signature:
void indsert(vector<int> arr, ...)
You pass the vector by value. That means a copy of the vector is made, and that copy is passed to the function.
You can modify this copy as much as you want, but the original vector will still not change.
You need to pass the vector by reference:'
void indsert(vector<int>& arr, ...)
// ^
// Note ampersand here, making this a reference
The second problem is much worse: You seem to assume that you can insert into a vector using the [] operator. That's not what's happening.
Instead you go out of bounds of the vector, which leads to undefined behavior.
You need to explicitly resize the vector, either using insert, push_back/emplace_back, or resize.
Also remember that since indexes are zero-based, the top-index is the same as the vector size minus one. Using the vector size as index will be out of bounds. Using the vector size plus one is even more out of bounds.
Your code exhibits undefined behaviour. You are accessing arr[size+1] in a vector arr of size size. Such a vector has values at positions 0 up to and including size-1.
If you want to append a value, use std::vector::push_back(). Alternatively you can std::vector::resize() the vector beforehand.
Also, you don't need to pass the size argument because std::vector::size() will tell you the current size of the vector. Furthermore, as has been pointed out to you, pass the vector by reference to avoid copying data for no reason.

Dynamic array of Linear search funcion implementation

Need to implement a function
int* linearSearch(int* array, int num);
That gets a fixed size array of integers with a number and return an array with indices to the occurrences of the searched number.
For example array={3,4,5,3,6,8,7,8,3,5} & num=5 will return occArray={2,9}.
I've implemented it in c++ with a main function to check the output
#include <iostream>
using namespace std;
int* linearSearch(int* array, int num);
int main()
{
int array[] = {3,4,5,3,6,8,7,8,3,5}, num=5;
int* occArray = linearSearch(array, num);
int i = sizeof(occArray)/sizeof(occArray[0]);
while (i>0) {
std::cout<<occArray[i]<<" ";
i--;
}
}
int* linearSearch(int* array, int num)
{
int *occArray= new int[];
for (int i = 0,j = 0; i < sizeof(array) / sizeof(array[0]); i++) {
if (array[i] == num) {
occArray[j] = i;
j++;
}
}
return occArray;
}
I think the logic is fine but I have a syntax problems with creating a dynamic cell for occArray
Also a neater implantation with std::vector will be welcomed
Thank You
At very first I join in the std::vector recommendation in the question's comments (pass it as const reference to avoid unnecessary copy!), that solves all of your issues:
std::vector<size_t> linearSearch(std::vector<int> const& array, int value)
{
std::vector<size_t> occurrences;
// to prevent unnecessary re-allocations, which are expensive,
// one should reserve sufficient space in advance
occurrences.reserve(array.size());
// if you expect only few occurrences you might reserve a bit less,
// maybe half or quarter of array's size, then in general you use
// less memory but in few cases you still re-allocate
for(auto i = array.begin(); i != array.end(); ++i)
{
if(*i == value)
{
// as using iterators, need to calculate the distance:
occurrences.push_back(i - array.begin());
}
}
return occurences;
}
Alternatively you could iterate with a size_t i variable from 0 to array.size(), compare array[i] == value and push_back(i); – that's equivalent, so select whichever you like better...
If you cannot use std::vector for whatever reason you need to be aware of a few issues:
You indeed can get the length of an array by sizeof(array)/sizeof(*array) – but that only works as long as you have direct access to that array. In most other cases (including passing them to functions) arrays decay to pointers and these do not retain any size information, thus this trick won't work any more, you'd always get sizeOfPointer/sizeOfUnderlyingType, on typical modern 64-bit hardware that would be 8/4 = 2 for int* – no matter how long the array originally was.
So you need to pass the size of the array in an additional parameter, e.g.:
size_t* linearSearch
(
int* array,
size_t number, // of elements in the array
int value // to search for
);
Similarly you need to return the number of occurrences of the searched value by some means. There are several options for:
Turn num into a reference (size_t& num), then you can modify it inside the function and the change gets visible outside. Usage of the function get's a bit inconvenient, though, as you need to explicitly define a variable for:
size_t num = sizeof(array)/sizeof(*array);
auto occurrences = linearSearch(array, num, 7);
Append a sentinel value to the array, which might be the array size or probably better maximum value for size_t – with all the disadvantages you have with C strings as well (mainly having to iterate over the result array to detect the number of occurences).
Prepend the number of occurrences to the array – somehow ugly as well as you mix different kind of information into one and the same array.
Return result pointer and size in a custom struct of yours or in e.g. a std::pair<size_t, size_t*>. You could even use that in a structured binding expression when calling the function:
auto [num, occurences] = linearSearch(array, sizeof(array)/sizeof(*array), 7);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// here the trick yet works provided the array is declared above the call, too,
// as is in your example
Option 4 would be my personal recommendation out of these.
Side note: I switched to size_t for return values as negative indices into an array are meaningless anyway (unless you intend to use these as sentinel values, e. g. -1 for end of occurrences in option 2).

Enter elements into dynamic (pointer-defined) array in C++?

I want to ask a question regarding entering elements in a dynamic array. I declare an array and then I want to enter elements in it. How can I do this using pointers into the array arr[] that I have declared previously?
Thanks in advance!
#include <iostream>
#include <algorithm>
using namespace std;
int *n = new int ;
int main()
{
cin>>*n;
int *arr = new int[*n];
int *i=new int;
for(*i=0; *i<=*n; *i++)
{
//Here, I should enter the elements but I cannot figure out how?
cin>>(*arr+i);
}
return 0;
}
While I question your usage of pointers for the size of the array and the index (They should just be int n; and int i = 0;, respectively), you can fix your code by using the subscript operator, or in code:
cin >> arr[*i];
Using pointer arithmetic is just unclear and makes it hard to tell what your goal is (In case you're wondering, the correct notation is *(arr+*i), which looks horrible IMO).
On a side note, consider using std::vector as a container, which will make your life a lot easier and prevent you from having to deal with pointers. Usage of std::vector may look like:
int main()
{
std::vector<int> arr;
for (int x; std::cin >> x;)
{
arr.push_back(x);
}
return 0;
}
This would prevent you from having to ask the user for the size of the std::vector as well and allow them to keep entering elements until they enter an EOF.
Here I am not changing your original approach at all so that you can understand pointer concept a bit more clear. As you know that array and pointer address calculation are exactly same. First you need to calculate the address and then dereference it. You just need to change it like below:-
cin>>*arr++;
Also you need to change your for loop like below:-
for(*i=0; *i<=*n; (*i)++)
But now after the above for loop you are going to face problem. The reason is that after storing each element in arr we have incremented the address of arr(arr++), so after the end of for loop arr is now pointing to the last element ( because arr = arr+*n). So first simply try with the below code:-
cout<<*arr<<endl<<endl;
if you have entered five numbers for example 0,1,2,3, and 4 the above statement will print some junk value as pointer is increment one more time.
now try with below:-
arr--;// Now arr will point to last element i.e. 4
cout<<*arr<<endl<<endl;
Hence you need one more int pointer and should store the first address of arr in it like below:-
int *arr = new int[*n];//exactly after this line of code
int *first = arr;
Now use a for loop to print the array:-
arr = first; //pointing to the first eliment
for(*i=0; *i<=*n; (*i)++)
{
//Here, I should enter the elements but I cannot figure out how?
cout<<*arr++<<endl;
}

C++: Remove element from dynamic struct array and shift other elements

I have an array of structs. I am trying to delete a list of elements from that array and shift other elements to the left. After shifting the elements I am trying to delete/free the memory at the end of the array which we don't require anymore. I have the following code:
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
void removeelement(int*);
void displayelements();
typedef struct {
int n;
}element;
element** array;
int numofelements=5;
int main() {
array = (element**)malloc(5*sizeof(element*));
for(int i=0;i<5;i++){
array[i] = new element;
array[i]->n=i;
}
int removelist[3] = {1,3,4};
removeelement(removelist);
displayelements();
return 0;
}
void removeelement(int* removelist){
for(int i=0;i<3;i++){
int index = removelist[i];
int j;
for(j=index;j<numofelements-2;j++){
array[j] = array[j+1];
}
delete [] array[j+1];
numofelements--;
}
}
void displayelements(){
int i=0;
while(i<numofelements){
printf("%d\n",array[i]->n);
i++;
}
}
But delete [] array[j+1]; is causing an exception:
*** Error in `main': double free or corruption (fasttop): 0x0000000001861cb0 ***
I don't understand what's causing this. As many people have suggested in other forums, I am using the 'new' operator to create a new,dynamic element.
EDIT:
I made the following changes:
I changed for(j=index;j<numofelements-2;j++){ to for(j=index;j<numofelements-1;j++){
int index = removelist[i] to int index = removelist[i]-i
I removed delete [] array[j+1] put delete array[numofelements+1] outside both the for loops.
Though I had used delete only on one element, It dealloced memory for the other redundant elements as well, which is interesting.
This is the final code:
#include <iostream>
#include<stdio.h>
#include<stdlib.h>
void removeelement(int*);
void displayelements();
typedef struct {
int n;
}element;
element** array;
int numofelements=5;
int main() {
array = (element**)malloc(5*sizeof(element*));
for(int i=0;i<5;i++){
array[i] = new element;
array[i]->n=i;
}
int removelist[3] = {1,3,4};
removeelement(removelist);
displayelements();
return 0;
}
void removeelement(int* removelist){
for(int i=0;i<3;i++){
int index = removelist[i]-i;
int j=index;
for(;j<numofelements-1;j++){
array[j] = array[j+1];
}
numofelements--;
}
delete array[numofelements+1];
}
void displayelements(){
int i=0;
while(i<5){
printf("%d\n",array[i]->n);
i++;
}
}
I got it working using this code. But I am going to use std::vector as many of you suggested.
You used delete[] expression on a pointer that was not returned by new[] expression. Therefore the behaviour of the program is undefined.
Anything that was allocated with new must be deallocated with delete. delete[] will not do.
Even if you had used the correct expression, there's another bug:
int numofelements=5;
//...
for(int i=0;i<3;i++){
int index = removelist[i];
int j;
for(j=index;j<numofelements-2;j++){
array[j] = array[j+1];
}
delete [] array[j+1];
numofelements--;
}
After the first iteration of the outer loop, array[4] has been deleted. Note that since removelist[i] == 1, I suspect that array[4] wasn't supposed to be deleted in the first place.
During the second iteration, array[4] will be deleted again. Since this points to the already deleted object, the behaviour is undefined.
Furthermore, copies of the deleted pointer remain in the array due array[j] = array[j+1] in the inner loop, while some of the pointers will be overwritten and therefore their memory will be leaked. Simple fix to your algorithm: Delete the pointer at index first, and shift elements after deletion.
Even more: If your loop worked as you intended, first 2 iterations would have each removed an element of the array, thus reducing numofelements to 3. Then, you'd be removing an element at index 4 of an array that has valid pointers in indices 0..2. Presumably the indices to be removed must be sorted; In that case, this can be fixed by deleting the index removelist[i] - i to acount for the shifts. Another clever strategy is to remove the indices from high to low, as suggested by Paul.
Other things to consider:
The program leaks the memory allocated for array. That might not be a problem to this trivial program, but it would be a good idea to have a habit of deallocating all memory that was allocated lest you forget to do so when it matters.
It's a bad idea to use malloc unless one has specific and reasonable justification to do so. One usually doesn't have a reasonable justification to use malloc.
It's a bad idea to allocate dynamic memory at all without using a RAII container. The bugs in this program would have been trivially been avoided if std::vector had been used.
Apart from the obvious errors in memory management, the approach in general could have been made simpler if you first sorted the removelist array, and then work backwards in that array starting from the last entry going toward the first entry.
Doing this would have changed the way the array was being resized in that you would have been doing the resizing (shifting elements) on entries that will no longer be affected. In your current code, you are shifting entries, and in subsequent iterations of the loop, you need to revisit those shifted entries with a now "invalid" removelist set of indices to remove.
See mayaknife's and user2079303 answers to illustrate the issue of invalid entries after removing each item (going from lowest entry to highest entry in the removelist array). As pointed out, even a usage of std::vector would not have helped you, since this issue points out the flaw in the basic logic being used to remove the elements.
Here is how you might have addressed this in your current code if you were to work going backwards in the removelist array ( I say "might have addressed", since this is not fully tested, but it illustrates more or less the point being made):
void removeelement(int* removelist)
{
for(int i = 2; i >= 0 ; --i)
{
int index = removelist[i];
array* elementToDelete = array[index];
for(j=index; j < numofelements -2; j++)
{
array[j] = array[j+1];
}
delete [] elementToDelete;
numofelements--;
}
}
Thus on each iteration, the removelist index will still be valid, since you're going from highest entry to lowest entry in the entries to delete. Work this out on paper and you see if you reversed the way you iterated through the removelist array, you should see how this works, as opposed to going forward through the removelist array.
You also have other issues with the code, such as mixing malloc with delete[]. Doing so is undefined behavior -- never mix allocation / deallocation methods like this in a C++ program.
Having said this, here is another version of your program, but not using manual memory management:
#include <vector>
#include <algorithm>
#include <iostream>
#include <array>
struct element {
int n;
};
int main()
{
std::vector<element> arr(5);
for (int i = 0; i < 5; ++i)
arr[i].n = i;
std::array<int, 3> removelist = {1,3,4};
// sort the list
std::sort(removelist.begin(), removelist.end());
// work backwards, erasing each element
std::for_each(removelist.rbegin(), removelist.rend(),[&](int n){arr.erase(arr.begin() + n);});
// output results
for( auto& v : arr)
std::cout << v.n << '\n';
}
Live Example
Note the usage of the reverse iterators rbegin() and rend(), thus mimicking the backwards traversal of the removelist container.
This line:
delete [] array[j+1];
deletes the array of elements pointed to by 'array[j+1]'. But 'array[j+1]' was initialized by this line:
array[i] = new element;
which only allocates a single element, not an array of elements, so the deletion should only delete a single element as well. E.g:
delete array[j+1];
The main problem, however, is that the wrong elements are being deleted. To see why, let's assume that the loop which initializes 'array' assigns it pointers to five 'element' structures which we will refer to as A, B, C, D and E.
Before the call to removeelements(), 'array' contains the following pointers:
array[0] -> A
array[1] -> B
array[2] -> C
array[3] -> D
array[4] -> E
'numofelements' is 5.
Inside removeelements(), the first element to be removed is 1 and the inner loop looks like this:
for(j=1;j<3;j++){
array[j] = array[j+1];
}
This will result in the contents of 'array[2]' being copied into 'array[1]' and 'array[3]' being copied into 'array[2]. After that 'array' contains the following:
array[0] -> A
array[1] -> C
array[2] -> D
array[3] -> D
array[4] -> E
At this point 'j' contains 3 so 'delete array[j+1]' will delete the element pointed to by 'array[4]', which is 'E'.
'numofelements' is then decremented to 4.
The second element to be removed is 3. Because 'numofelements' is now 4, the inner loop will look like this:
for(j=3;j<2;j++){
array[j] = array[j+1];
}
'j' will be initialized to 3. That is greater than 2 so the body of the loop won't execute and 'array' will be left unchanged.
Since 'j' is 3 'delete array[j+1]' will again delete 'array[4]', which still points to E. So E is deleted a second time, resulting in the error that you are getting.
Were the program to continue, 'numofelements' would be decremented to 3 and we'd move on to the third element to be removed, which would be 4. This would give an inner loop like this:
for(j=4;j<1;j++){
array[j] = array[j+1];
}
'j' would be initialized to 4 and once again the body of the loop would not be executed. 'delete array[j+1]' would attempt to delete the element pointed to by 'array[5]', which is beyond the bounds of 'array' and would result in an exception.
As others have suggested, the best way to handle this is to use std::vector. However, the way your code is structured even std::vector will fail to give you the results you want because as soon as you delete one element from 'array' the indices of all of those which follow it will change, meaning that the remaining indices in 'removelist' will no longer be correct.
I suggest that whatever changes you make, you manually step through the code, as I have above, tracking the contents of the array and relevant variables so you can understand exactly what your code is doing.

While inserting nodes in heap how to use bubble up?

Following is my code which doesnot properly bubbles up the larger value .Can any one help out .The problem is somewhat at count++ .
#include<iostream>
using namespace std;
class heap{
public:
int count;
heap(int c)
{
count=c;
}
int Arr[10];
void insert(int num);
void deletemax();
void print();
};
void heap::insert(int num){
if(count==10){
cout<<"Heap full\n";
exit(1);
}
else{
Arr[count]=num;
count++; //The real problem arises here that the compiler adds 1 to count and when the code moves ahead it sets position var to count++ value and tries to compare a value at Arr[POS] with its parent whereas there is no value at this place set uptill.
}
int POS=count;
while(Arr[POS]>Arr[(POS-1)/2]){
int temp;
temp=Arr[POS];
Arr[(POS-1)/2]=temp;
POS=(POS-1)/2;
}
}
void heap::print(){
for(int i=0; i<10; i++){
cout<<Arr[i]<<endl;
}
}
int main(){
heap h(0);
int a;
int b=0;
while(b<10){
cout<<"Insert node in heap\n";
cin>>a;
h.insert(a);
b++;
}
h.print();
return 0;
}
I would agree, that's where your problem is.
There are many issues with the code you posted, some of which include:
As to your specific issue, I would guess you need to change the line in heap::insert() to "int POS=count-1;" to properly start iterating from the back of the array.
You need to consider the case of adding an element to an empty array and what then happens in your sorting code.
Your constructor allows someone to create a heap that will overflow the fixed sized array, for example heap(1000). In addition, the Arr member is not initialized which means it has undefined data for any value but heap(0). In this case your constructor should not take any parameters and count should just be initialized to 0.
The purpose of the code is confusing. Is it a heap, a sorted array, an attempt to approximate a heap with an array, none of the above? If you are simply trying to implement a fixed sized sorted array then I believe your sorting code in insert() will not work (e.g., consider adding 100 to a heap containing [1,2,3]).
There are other, more basic things, wrong (like not using any the STL containers, public class member, non-const parameter passing, "using std", etc...) but I'm assuming you are merely experimenting/playing here.