C++ dynamic array, increasing capacity - c++

I'm trying to implement a dynamic array and here is my function for increasing the capacity
int* changeCapacity(int *arr, int length, int newCapacity) {
int *newArr = new int[newCapacity];
if(length > newCapacity){
return 0;
} else {
for(int i = 0; i < length; i++){
newArr[i] = arr[i];
}
delete[] arr;
arr = newArr;
return arr;
}
}
This is the error i get:
speicher(2465,0x7fff7cfc2310) malloc: * error for object 0x7f9742403910: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
i'm calling it like this:
int* addElement(int *arr, int& length, int& capacity, int val){
if(length >= capacity){
capacity = capacity * 2;
changeCapacity(arr, length, capacity);
arr[length] = val;
length += 1;
return arr;
}else{
arr[length] = val;
length += 1;
return arr;
}
}

I assume that your problem must come from two things IMO :
First:
changeCapacity(arr, length, capacity);
arr[length] = val;
Here you doesn't get the new arr value (returned by changeCapacity()).
So your function addElement() will return Wrong pointer and on your next addElement() that will do free memory corruption.
Why do you have to get the new arr value?
You do the same as here
a = 1;
changeVar(a);
// value of a here?
int changeVar(int a)
{
a = 5;
return (a);
}
How will be the value of a? 1 because the argument of changeVar is a local variable.
Second:
You give a NULL value on your addElement() function.

Right now you are changing the address of arr, in which you have to pass the pointer by reference. Do this:
int* changeCapacity(int *&arr, int length, int newCapacity)

This is somewhat a guess based on the error message, but you have shown:
int* addElement(int *arr, int& length, int& capacity, int val)
{ //...
changeCapacity(arr, length, capacity);
//...
}
which calls:
int* changeCapacity(int *arr, int length, int newCapacity)
{ //...
delete[] arr;
//...
}
However, the original source of the arr argument to addElement() is unknown given the code you have posted so far. Are you by chance doing something like this:
foo()
{ int array[N];
//...
addElement(array, ...);
//...
}
or maybe calling addElement() with a global array variable? In either of those cases, the original array is not allocated via a new[] to match the delete[], and this would appear to be what the runtime library is complaining about. The value of the pointer stated in the error message tends to make me think it was allocated on the stack initially.
Of course the other issues, like not capturing the return value of changeCapacity() and/or addElement(), and the possibility that changeCapacity() might return a NULL pointer are still valid as well, and should be fixed.

Here is a better way of doing it. Everything is well explained in the comments for anyone who wants to learn:
#include <iostream>
using namespace std;
int* changeCapacity(int *arr, int length, int newCapacity);
int* addElement(int *arr, int& length, int& capacity, int val);
int main(){
int length = 0; // no inital elements in array
int capacity = 1; // initial capacity is one
int* arr = new int[capacity]; // allocating space for values
int* temp; // pointer for storing temporary values
/* loop for adding elements to the array */
for(int i=0;i<21;i++){
temp = addElement(arr,length,capacity,i); // adding an element to the array
if(temp == NULL) { // checks if execution was successful
cout<< "NULL returned...\n Exiting Now...";
return 0; // exits the program on failure
}
arr = temp; // changing the value of arr
}
/* loop for printing the array */
for(int i=0;i<length;i++){
cout<<arr[i]<<" ";
}
return 0;
}
/* function for increasing the capacity of array */
int* changeCapacity(int *arr, int length, int newCapacity) {
int *newArr = new int[newCapacity]; // definging a new array
if(length > newCapacity){ // checking if the length of the array is valid
cout<< "invalid length of array\n";
return NULL;
} else {
/* loop for transferring values to the new array */
for(int i = 0; i < length; i++){
newArr[i] = arr[i];
}
delete[] arr; // deleting the old array (clears the memory of the old array)
// arr = newArr; removed as this is not needed
return newArr; // returns the new array
}
}
/* function for adding a new element to the array */
int* addElement(int *arr, int& length, int& capacity, int val){
if(length >= capacity){ // checks if the array has space for storing the given value or not
capacity = capacity * 2; // doubles the capacity of the array
int* temp = changeCapacity(arr, length, capacity); // changes the size of the array to the new one
if(temp == NULL){ // checking if a null was returned
cout<< "Failed to change capacity\n";
return NULL; // returning NULL
}
arr = temp; // the value of arr was not changed in your code (problem corrected)
arr[length] = val; // stores the value in the array
length += 1; // increasing the number of element count of the array
return arr; // returns the new array
}else{
arr[length] = val; // stores the value in the array
length += 1; // increasing the number of element count of the array
return arr; // returns the new array
}
}

Related

2d Array to a function expecting int** array as parameter

I want to use a function made for dynamic arrys for an pre-initialised array too.
int MinInRow(int** fieldArray, int value, int currentColumn, int maxNumColumns)
{
int minVal = 0;
for (int inkrCol = 0; inkrCol < maxNumColumns; inkrCol++)
{
if (feldArray[currentColumn][inkrSpalte] < value)
{
minVal = feldArray[currentColumn][inkrCol];
}
}
return minVal;
}
So if I try
int testArray[3][4] =
{ {4,5,6,7},
{0,1,2,3},
{9,8,10,11}, };
int (*bufferArray)[4] = testArray;
or...
int** bufferArray = testArray;
or...
...
int main()
{
/*
read in other needed parameters
....
*/
std::cout << MinInRow((*bufferArray)[4], int value, int currentColumn, int maxNumColumns);
retrun 0;
}
I cant compile. But shouldnt int** bufferArray = testarray; just work fine? I mean there is always an double pointer to the first address of an 2D-Array.
how can I hand it over to the MinInRow-function? Thanks!
There is a little problem. "*" That one tell you that you want to make a pointer, but a pointer doesn't want a variable, he want the address. And then you've written
int** bufferArray = testarray.
You should write
int* bufferArray = new int [size of array] It's for 1D array
and ....
int** bufferArray = new int* [rows];
for (size_t = 0 ; i != rows ; ++i){
bufferArray[i] = new int [colons];
}
for 2D array
"I cant compile. But shouldnt int** bufferArray = testarray; just work fine? I mean there is alway an double pointer to the first address of an 2D-Array."
And Yes, it will be work nice. If testarray already 2D array

Passing pointer to an array into a function (C++)

I'm trying to pass an array into my function calls for build_max_heap and max_heapify so I can modify the array after each call, but I receive an error saying "candidate function not viable: no known conversion from 'int [9]' to 'int *&'for 1st argument."
#include <iostream>
#include <string>
using namespace std;
void build_max_heap(int*& array, int size);
void max_heapify(int*& array, int size, int index);
void build_max_heap(int*& array, int size)
{
for(int i = size/2; i>=0; i--)
{
max_heapify(array, i);
}
}
void max_heapify(int*& array, int size, int index)
{
int leftChild = 2*index+1;
int rightChild = 2*index+2;
int largest;
int heap_size = size;
if( leftChild <= heap_size && array[leftChild] > array[index])
largest = leftChild;
else
largest = index;
if(rightChild <= heap_size && array[rightChild] > array[largest])
largest = rightChild;
if(largest != index) {
int tempArray = array[index];
array[index] = array[largest];
array[largest] = tempArray;
max_heapify(array, heap_size, largest);
}
}
int main()
{
int array[]={5,3,17,10,84,19,6,22,9};
int size = sizeof(array)/sizeof(array[0]);
build_max_heap(array, size);
return 0;
}
int array[]={5,3,17,10,84,19,6,22,9};
While array can be decayed to a pointer int* to be passed as a function argument, it the pointer cannot be passed as a "non-const reference" int*&, because it is immutable (it is a constant address). You could have passed it as a const reference like this:
void max_heapify(int* const& array, int size, int index)
// ^^^^^^
However, this doesn't make much sense, you can simply pass the pointer by value (a copy of the address of the array), which results in the same: the variable at the caller wont be changed. The usual use case of const& parameters is to pass objects that are expensive to copy, such as std::string. This does not apply to pointers; making a copy of a pointer is as cheap as copying any basic variable.
You should change your functions to take the pointer by value:
void build_max_heap(int* array, int size)
void max_heapify(int* array, int size, int index)
also, correct the call to max_heapify inside build_max_heap, give it the correct number of arguments:
void build_max_heap(int* array, int size)
{
for(int i = size/2; i>=0; i--)
{
max_heapify(array, size, i); // <-- 3 arguments
}
}

How to pass a pointer array to a function as pass by reference?

How to pass a pointer array to a function as pass by reference?
I am passing a dynamic array to a function which is working correct within the function but i am unable to pass the pointer array as pass by reference.
I know that array is passed by default as pass by reference.
Thanks
#include <iostream>
using namespace std;
void printArray(int *arr, int SIZE){
for (int i = 0; i < SIZE; i++)
cout << arr[i] << ' ';
cout << endl;
}
void addData(int *arr, int &SIZE, int data){
int *temp = new int[SIZE];
for (int i = 0; i < SIZE; i++){
arr[i] = i;
temp[i] = arr[i];
}
printArray(temp, SIZE); //Output is: 0 1 2 3 4
printArray(arr, SIZE); //Output is: 0 1 2 3 4
delete arr;
arr = NULL;
arr = new int[SIZE+1];
for (int i = 0; i < SIZE; i++)
arr[i] = temp[i];
arr[SIZE] = data;
SIZE++;
printArray(arr, SIZE); //Output is: 0 1 2 3 4 5
delete temp;
temp = NULL;
}
int main(){
int SIZE = 5;
int *arr = new int[SIZE];
addData(arr, SIZE, 5); //Extend the array by one index to insert data
printArray(arr, SIZE); //Output is: Some garbage values but Output should be: 0 1 2 3 4 5
cout << endl;
system("PAUSE");
return 0;
}
When you call int *arr = new int[SIZE]; you have allocated memory to store SIZE of int and arr is pointing to this memory.
Inside addData function you call arr = new int[SIZE+1]; expecting arr to be now pointing to a memory filled with new values when the function returns. However when int *arr is passed to void addData(int *arr, int &SIZE, int data) it gets copied. The pointer variable arr has the same value as an outer variable but they are referencing different places. After arr = new int[SIZE+1]; inner variable no longer points to the same place as an outer one.
When you call printArray your outer arr will have the same garbage as it had when you called int *arr = new int[SIZE];.
You can accept arr argument by reference like void addData(int* &arr, int &SIZE, int data) to fix the problem. This will make sure that inner variable will be stored in the same place as an outer one persisting changes.
You might be confused about the fact that you actually pass a pointer and observing no changes persistence. The changes are actually persisted for the array elements. For example if you write arr[0] = 2 in the function those changes will be present after function ends. But changes with the pointer variable itself are not persisted.
Function header should be
void addData(int &*arr, int &SIZE, int data)

Returning an integer array

This is one the methods that I have to make for my assignment
int*mode(int &) – returns an integer array containing the modal value(s) of the
population, the reference parameter should be set to the size of the result
But from searching, you cannot return array's from a function? I can calculate modal value from a given array, put it in an array, but return an integer array? maybe the professor meant something else? I know how to do all other methods except that one. I don't even know what that method means (Coming from java)
Header File
#include <string>
using namespace std;
class population
{
public:
//Default Constructor
population(void);
//Constructor that accepts an integer array object, and the size for that array object
population(int[], int);
//Constructor for creating a deep copy
population (const population &);
//For overloading purposes
population & operator = (const population &);
//Destructor that frees dynamic memory associated with the underlying array
~population(void);
//Method for loading new content into an array
void load(string);
//Method for adding new content into existing array
void add(string);
//Accessors
//Returns the size of the population (The number of values stored in the array)
int size();
//Returns the sum of the popluation (The sum of the contents in the array)
int sum();
//Returns the mean of the population
float mean();
//Returns the median of the population
float median();
//Returns the standard deviation of the population
float stddev();
//Returns an integer array containing the modal values of the popluation
int*mode(int &);
private:
int arraySize;
bool sorted;
int * popArray;
};
CPP
#include "population.h"
//Default Constructor
population::population(void)
{
}
//Constructor to intialize the population object
population::population(int arr[], int s)
{
//Store s into a variable
arraySize = s;
//Declare popArray as a Dynamic array
popArray = new int[arraySize];
//Copy the passed array into the popArray
for ( int i=0; i < s; i++)
{
popArray[i] = arr[i];
};
}
//Constructor for deep copying purposes
population::population (const population & p)
{
}
population::~population(void)
{
}
int population::size(void)
{
//Return size of the array, which is the amount of population in the array.
return arraySize;
}
int population::sum(void)
{
//Variable to hold sum of the array
int sumArray = 0;
//Add all the contents of the array into one variable
for ( int i = 0; i < arraySize; i++)
{
sumArray += popArray[i];
}
//Return the sum of the array
return sumArray;
}
float population::mean(void)
{
//Variable to hold sum and the mean of the array
int sumArray = 0;
float meanArray;
//Add all the contents of the array into one variable
for ( int i=0; i < arraySize; i++)
{
sumArray += popArray[i];
}
//Sum of the array divided by number of contents in the array (Average)
meanArray = (sumArray / arraySize);
//Returns mean value in type float
return meanArray;
}
float population::median ()
{
return 1;
}
float population::stddev()
{
return 1;
}
int population::*mode(int & i)
{
return
}
With a prototype like that, I'm guessing that he wants you to new an array to be returned:
int *population::mode(int & i)
{
// compute the number of modal values you need to return
i = /* whatever the size of the return array will be */;
int * ret = new int[i];
// fill in ret
return ret;
}
Try:
int foo(int arrayBar[])
or
int foo(int* arrayBar)
or
int* foo(int arrayBar[])
If those don't work, make sure your pointer is at the beginning of the array.
Source: Return array in a function

Why does an array of pointers initializes itself when function finishes?

My weekend assignment was to make a function that gets an array of integers and the size of the array, and creates an array of pointers so that the pointers will be sorted using bubble sort (without changing the original array).
While debugging I found out that it works just fine, but when the function goes back to main() the pointers array gets initialized and everything's gone.
#include <iostream>
using namespace std;
void pointerSort(int arr[], int size, int* pointers[]);
void swap(int a, int b);
void main()
{
int arr[5]={7,2,5,9,4};
int size = 5;
int* pointers[5];
pointerSort(arr, size, pointers);
for (int i = 0; i < 5 ; i++)
cout << *pointers[i] << endl;
}
void pointerSort(int arr[], int size, int* pointers[])
{
int j, i;
bool change = true;
pointers = new int*[size];
for (i = 0; i < size; i++)
pointers[i] = &arr[i];
i = 0;
j = 1;
while (i <= size-1 && change == true)
{
change = false;
for (i = 0; i < size-j; i++)
{
if (*pointers[i] > *pointers[i+1])
{
swap(pointers[i], pointers[i+1]);
change = true;
}
}
j++;
}
}
void swap(int&a, int&b)
{
int temp;
temp = a;
a = b;
b = temp;
}
pointers = new int*[size];
At this point pointers is already an array of pointers, no allocation is needed.
After this line pointers IS NO LONGER THE ARRAY IN YOUR MAIN FUNCTION.
This is why your function is failing, because you are reassigning the array to which pointers is pointing to. The original array ISNT getting reinitialized, its just ignored throughout the entire code.
It is also a memory leak as ATaylor mentions, since you do not delete the allocated space, and cannot delete the space after the function finishes.
To fix everything: just remove the above line.