This is my simple program that has two functions, one is to create a series of Fibonacci then add it to an array. Another one is used to deallocate the array, but it doesn't work. Can someone help me?
int **createFibArray(int n){
int **arr = new int*[n];
int fnum1 = 1,fnum2=1,fnum;
// n== 1
if(n == 1){
arr[0] = new int;
*arr[0] = 1;
return arr;
}
// n>= 2
arr[0] = new int;
arr[1] = new int;
*arr[0] = 1;
*arr[1] = 1;
// fib calculator
for(int i=2; i<n; i++){
fnum = fnum1 + fnum2;
fnum1 = fnum2;
fnum2 = fnum;
arr[i] = new int;
*arr[i] = fnum;
}
return arr;
}
//This function takes an array pointer, and deallocates memory
void removeArray(int head[]){
delete [] head;
head = nullptr;
}
int main(){
int **head = createFibArray(10);
for(int i=0;i<10;i++){
cout << *head[i] << endl;
}
cout << "------" << endl;
removeArray(*head);
for(int i=0;i<10;i++){
cout << *head[i] << endl;
}
return 0;
}
You need to strongly consider returning an array of integers rather than an array of integer pointers. If you insist on using a raw pointer rather than an STL container:
int **createFibArray(int n)
Should be
int *createFibArray(int n)
And this:
int **arr = new int*[n];
will be this:
int *arr = new int[n];
Then you can remove the * from nearly every place you use it, and the delete function can remain pretty much unchanged. You will change the call to the delete function:
removeArray(*head);
becomes:
removeArray(head);
However, setting the value to nullptr in the function is worthless. either do so after the call to removeArray or omit it entirely if you are certain it will never be reused after being deleted.
Which brings us to the last part of your main function. Dereferencing a pointer after you have deleted it (or attempted to delete it in this case) is undefined behavior.
Related
I am trying to implement a dynamically created array using new that I want to resize but the resize action is not working correctly.
This is an exercise on dynamic arrays, so I need dynamic arrays using new and not std::vector.
Here is my code :
int main ()
{
// Build an application here
int length = 0;
int size = 0;
int input;
bool endAdding = false;
cout << "Please enter the length of the new array : ";
cin >> length;
int* oPtrDynamicArray = CreateDynamicArray (length, size);
do
{
cout << "Add an element (0 to quit) : " << endl;
cin >> input;
cout << endl << endl;
if (input == 0){
endAdding = true;
}
else
{
InsertElement(oPtrDynamicArray, input, size, length);
}
cout << "The array contains : " << endl;
for (int i = 0; i < size; i++)
{
cout << i << ": [" << oPtrDynamicArray[i] << "]" << endl;
}
} while (!endAdding);
DeleteDynamicArray (oPtrDynamicArray, size);
}
int *CreateDynamicArray (int capacity, int &size)
{
size = 0;
return new int[capacity];
}
void DeleteDynamicArray (int *dynamicArray, int &size)
{
delete[] dynamicArray;
dynamicArray = nullptr;
size = 0;
}
void InsertElement (int *dynamicArray, int element, int &size, int capacity)
{
if (capacity <= size)
{
ResizeDynamicArray (&dynamicArray, size+1);
}
dynamicArray[size] = element;
size++;
}
void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
int ** newArray = new int*[newCapacity];
for (int i = 0; i < newCapacity; i++)
{
newArray[i] = dynamicArray[i];
}
*dynamicArray = *newArray;
delete[] newArray;
newArray = nullptr;
}
The problem is that the array is passed to my InsertElement() function and then to ResizeDynamicArray() only if capacity <= size, but the array passed to the first function, is passed with good values, but with abnormal pointers in the array.
Example :
For an array of 3, I have :
array[0] = 1 --> adress 0x0004e300 containing value 1
array[1] = 2 --> adress 0x00000003 containing ???
array[2] = 3 --> adress 0x008ffb24 containing value 2
I really don't understand, it would be really great if someone could explain my error :/.
The problem is here
void InsertElement (int *dynamicArray, int element, int &size, int capacity)
{
if (capacity <= size)
{
ResizeDynamicArray (&dynamicArray, size+1);
}
dynamicArray[size] = element;
size++;
}
when you call ResizeDynamicArray you are changing the dynamicArray pointer declared as a parameter to InsertElement. You are not changing the oPtrDynamicArray pointer in main.
If you want to make this work you need to change InsertElement to take a double pointer (just like ResizeDynamicArray)
void InsertElement (int **dynamicArray, int element, int &size, int capacity)
{
if (capacity <= size)
{
ResizeDynamicArray (dynamicArray, size+1);
}
(*dynamicArray)[size] = element;
size++;
}
Or you could do the easy thing and just use std::vector<int>.
EDIT now that I look at it your ResizeDynamicArray function I see that function is completely wrong as well. It's clear that you have some learning to do with pointers
Here's how ResizeDynamicArray should be
void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
int * newArray = new int[newCapacity];
for (int i = 0; i < newCapacity; i++)
{
newArray[i] = (*dynamicArray)[i];
}
delete[] *dynamicArray;
*dynamicArray = newArray;
}
You're not the first newbie to fail to understand pointers. Have a good look at the code above and compare it with your code. The main difference is that my code using a pointer to change what is being pointed to. Your code tried to change the pointer itself, which is incorrect. It's confusing because what is being pointed to is another pointer (the dynamic array).
There are several issues in your code:
First, in ResizeDynamicArray, you allocate an array of pointers to ints, not an array of ints. int ** newArray = new int*[newCapacity] should be int *newArray = new int[newCapacity].
Second, once you have fixed that, you need to write *dynamicArray = newArray;;
but you should free the old array before you assign the pointer to the new memory block.
void ResizeDynamicArray (int **dynamicArray, int newCapacity)
{
int *newArray = new int[newCapacity];
for (int i = 0; i < newCapacity; i++)
{
newArray[i] = (*dynamicArray)[i];
}
delete[] *dynamicArray;
*dynamicArray = newArray;
}
Third, you since InsertElement may call ResizeDynamicArray (which will give you back a new memory block), you need to alter the originally passed pointer. So you need to pass a pointer to a pointer int the function, just as you did with ResizeDynamicArray:
void InsertElement (int **dynamicArray, int element, int &size, int capacity)
adapt the body accordingly then.
I know the question is already answered but not the why.
You have to keep in mind that pointers are passed to functions by value.
The pointer value, the address it points to, is lost when the function ends.
But you are still able to change the value stored at the address it points to by dereferencing the pointer.
To pass be able to change the pointer value, the address it points to, inside a function, you have to pass a pointer to a pointer. In this case passing a double pointer is synonym for passing a pointer to a function by reference.
void Foo(int **ptr)
{
// Don't use ptr, changes are lost after function end as ptr is a local copy
// Use *ptr to change the value of the pointer you passed to the function.
// Use **ptr to change the value at the address the pointer you passed to the funcion points to
}
In this case you can change the pointer value, the address it points to, by dereferencing the double pointer once. Which applies to above answers.
I need to implement a function that modifies an array. The new array may be a different size. cout prints 1. I understand what's wrong with this code but I just cannot figure out what the syntax is.
//tried this..
int reduce(int *array[])
{
*array = new int[1];
(*array)[0] = 6;
return 0;
}
//also tried this..
int reduce(int array[])
{
array = new int [1];
array[0] = 6;
return 0;
}
int main()
{
int a[1] = {1};
int *p = a;
reduce(&p);
cout << a[0];
return 0;
}
Don't understand your question correctly, but this is what you may do:
void reduce(int *a, int size)
{
for (int i =0; i < size; ++i) {
*(a+i) = 6; // or whatever value to want to
}
}
Call it this way:
int main(){
int a[5] = {1, 1, 1, 1, 1};
int *p = a;
reduce(p, 5);
for (int i =0; i < 5; ++i) { cout << a[i]<<endl; }
return 0;
}
EDIT
What you are trying to do can be vaguely done this way:
int * reduce (int **b, int size) {
*b = new int[size];
for (int i =0; i < size; ++i) {
*(*b + i) = 6;
}
return *b;
}
int main(){
int a[5] = {1, 1, 1, 1, 1};
int *p = a;
p = reduce(&p, 5);
cout << p[0];
cout << p[1];
cout << p[2];
cout << p[3];
cout << p[4];
delete [] p;
return 0;
}
But it still wont change where a is pointing to.
What you are trying to do is not possible with statically defined arrays.
When you use an array like
int a[1] = {1};
you cannot change the size of the array at run time, you cannot make it point to dynamically allocated memory. You may only access and modify the elements the array. That's it.
The function reduce changes where p points to but it does not change the elements of a.
If you want to modify the contents of a, you can simply use a as an argument, and set the values.
MODIFIED:
You want to modify array a, try this :
int reduce(int **array)
{
*array = new int[1];
(*array)[0] = 6;
return 0;
}
int main()
{
int *a = new int[1];
reduce(&a);
cout << a[0];
return 0;
}
First of all, the formal parameter int* array[] actually is the same as int** array (you can think of it as a two-dimensional array). This is probably not what you want.
The answer of #everettjf will only work if you do not change the size of the array. A possible solution (that completely replaces the array) would be
#include <iostream>
void print_array(int[],int);
int* reduce(int array[]) {
// get rid of the old array
delete[] array;
// create a new one
array = new int[7]{8,4,6,19,3,56,23};
// need to return the new address, so that
// the main function is informed on the new
// address
return array;
}
int main() {
// initialize array
int *a = new int[1]{4};
print_array(a,1);
// "change" array by completely replacing it
a=reduce(a);
print_array(a,7);
return 0;
}
// simply prints out the array; no error checking!
void print_array(int array[], int length) {
std::cout << "[";
for (int i = 0; i < length ; ++i) {
std::cout << array[i] << " ";
}
std::cout << "]" << std::endl;
}
In the reduce function, the initial array is completely deleted. Afterwards, you can create a new one (I chose to just use 7 random numbers). It is important to return that pointer back to the caller (the main method). Otherwise the a pointer in the main method would point to invalid
If you are not forced (by some kind of excercise, for example) to use arrays, you should look into http://en.cppreference.com/w/cpp/container/vector
The premise of your question is invalid. It is not possible to resize an array of automatic storage duration (aka a in main()) after its definition by ANY means in standard C++.
Dynamic memory allocations in either of your reduce() functions will not cause a in main() to be resized.
reduce(&p) will calls the first version of reduce() , which will then change p (so it points at the dynamically allocated memory) but not affect a.
If main() calls reduce(a) or reduce(p) (the two are equivalent, given the initialisation int *p = a) will change neither a nor p, but instead cause a memory leak.
The underlying problem, I suspect, is that you believe - incorrectly - that pointers and arrays are the same thing. They are actually different things, but can be used in the same way in various contexts. And your code is one of the contexts in which they cannot be used interchangeably.
If you want a resizeable array, use a static container (like std::vector<int>) and - if you want a function to resize it, pass it by reference. It manages its own memory dynamically, so is able to dynamically resize itself.
Ok so I am going to lay out two programs. Both are dynamic arrays using pointers and the new operator. But one doesn't seem to like the delete operator.
#include <iostream>
int main()
{
int *p;
p = new int[5];
for (int i = 0; i < 5; i++)
{
p[i] = 25 + (i * 10);
std::cout << p[i] << " ";
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
That's the first program. It likes the delete operator just fine. Now the program that dislikes the delete operator:
#include <iostream>
int main()
{
int x;
int *p;
p = new int[5];
*p = 4;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
This program compiles just fine. But during execution, it throws an error - free(): invalid pointer: 0xfdb038 .. or whatever the memory address is for that particular execution. So, the question is:
Why can't the delete operator be used in the second case?
I don't want to have memory leak; I don't want the pointer to be dangling.
If I just say p = NULL;, then p = 0, but I believe the pointer is still dangling?, but I'm not sure. Thanks in advance.
Look at this loop in the second piece of code:
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1; // <--- Here
}
Notice that in this line, you write to the memory address currently pointed at by p. Since you always increment p and then write to it, you end up writing off past the end of the region that you allocated for p. (If we imagine pOrig as a pointer to where p initially points, then this writes to pOrig[1], pOrig[2], pOrig[3], pOrig[4], and pOrig[5], and that last write is past the end of the region). This results in undefined behavior, meaning that literally anything can happen. This is Bad News.
Additionally, delete[] assumes that you are passing in a pointer to the very first element of the array that you allocated. Since you've incremented p so many times in that loop, you're trying to delete[] a pointer that wasn't at the base of the allocated array, hence the issue.
To fix this, don't write to p after incrementing it, and store a pointer to the original array allocated with new[] so that you can free that rather than the modified pointer p.
You have to delete the pointer that you got from new. However, in your second code you did p++ which changed the pointer. Therefore you tried to delete a pointer you didn't get from new and delete crashes.
To fix this type of error never use new. Instead use std::vector<int> p;. Since you never need new you cannot forget a delete.
Problem is changing p in p++.
You should always store (to delete) original pointer. Like this:
#include <iostream>
int main()
{
int *original = new int[5];
int *p = original;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
int x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] original;
return 0;
}
So I know multiple dimensions/arrays can get confusing, but how do I delete these types of arrays properly? I know the syntax, but adding multiple dimensions/pointers gets tricky. Here's some snippet code:
//FIRST PROBLEM
//function to add an item to a pointer array
//due to problems in adding something directly, I created a temp
//temp is not necessary if there's a way without it
int y = 6;
int x = 5;
int *myList = new int[x];
void List::add(int newInt)
{
void List::add(int newInt){
int *temp = new int[x+1];
temp = myList;
temp[x+1] = newInt;
delete [] myList;
int *myList = temp;
}
//SECOND PROBLEM----tricky multidimensional
// not getting any errors, but not sure if done properly
int x;
int y;
int** myMatrix;
cout << "How many rows?" << endl;
cin >> x;
myMatrix = new int*[x];
cout << "How many columns?" << endl;
cin >> y;
for (int i=0; i<x; i++)
myMatrix[i] = new int[y];
for(int i=0; i<10; ++i){
for(int j=0; j<10; ++j){
myMatrix[i][j] = rand();
}
for(int i = 0 ; i < x ; ++i)
{
for(int j = 0 ; j < col ; ++j){
// delete[] myMatrix[i][j]; (tried this method, did not work)
}
delete[] myMatrix[i];
}
delete[] myMatrix;
//looked around for examples, but were all different enough to not help
//
// delete[] myMatrix[i][j]; (tried this method, did not work)
The code you have here
myMatrix[i][j] = rand();
doesn't allocate any new heap memory for myMatrix[i][j] (which is of a non pointer type, but a simple int BTW), but just assigns the result of rand() as a value there.
Thus it's not necessary/wrong, you ever call delete for it.
You only call delete/delete[] as counterparts of new/new[] in the reverse order as they were allocated.
Further, to get redeemed from struggling with memory management, I'd seriously recommend using a c++ standard container like std::vector<std::vector<int>> myMatrix; instead of managing raw pointers.
I am learning about pointers and the new operator in class.
In my readArray function I am to read in a size. Use the size to dynamically create an integer array. Then assign the array to a pointer, fill it, and return the size and array.
I believe I've gotten that part corrected and fixed but when I try to sort the array, i get the error "uninitialized local variable temp used."
The problem is though I get that error when I am trying to intialize it.
Any help appreciated thank you. Seeing my errors is very helpful for me.
#include <iostream>
using namespace std;
int* readArray(int&);
void sortArray(int *, const int * );
int main ()
{
int size = 0;
int *arrPTR = readArray(size);
const int *sizePTR = &size;
sortArray(arrPTR, sizePTR);
cout<<arrPTR[1]<<arrPTR[2]<<arrPTR[3]<<arrPTR[4];
system("pause");
return 0;
}
int* readArray(int &size)
{
cout<<"Enter a number for size of array.\n";
cin>>size;
int *arrPTR = new int[size];
for(int count = 0; count < (size-1); count++)
{
cout<<"Enter positive numbers to completely fill the array.\n";
cin>>*(arrPTR+count);
}
return arrPTR;
}
void sortArray(int *arrPTR, const int *sizePTR)
{
int *temp;
bool *swap;
do
{
swap = false;
for(int count = 0; count < (*sizePTR - 1); count++)
{
if(arrPTR[count] > arrPTR[count+1])
{
*temp = arrPTR[count];
arrPTR[count] = arrPTR[count+1];
arrPTR[count+1] = *temp;
*swap = true;
}
}
}while (swap);
}
You make temp an int pointer (uninitiialized), and then set the thing it points at (anything/nothing) to arrPTR[ccount]. Since you are using temp only to swap, it should be the same type as those being swapped, in this case: an int.
If it absolutely must be a pointer (there is no good reason for this, it's slow, confusing, adds potential for errors, and adds potential for memory leaks):
int *temp = new int; //make an int for the pointer to point at
bool *swap = new bool; //make an bool for the pointer to point at
do
{
//your code
}while (swap);
delete temp;
delete swap;
You declared temp as a pointer. You need to allocate it on the heap before dereferencing and assigning to it later. However perhaps a variable on the stack would be preferable?
FYI: You should be aware of the memory leak in readArray as well which is leaving callers responsible for calling delete []
Edit: I hope this will help clear up some of the other problems.
#include <iostream>
int* readArray(int&);
void sortArray(int*, int);
int main ()
{
int size(0); // use stack when possible
int *arrPTR = readArray(size);
sortArray(arrPTR, size);
// arrays are zero based index so loop from 0 to size
for (int index(0); index < size; ++index)
std::cout << arrPTR[index];
delete [] arrPTR; // remember to delete array or we have a memory leak!
// note: because we did new[] for an array we match it with delete[]
// if we just did new we would match it with delete
system("pause");
return 0;
}
int* readArray(int& size)
{
std::cout << "Enter a number for size of array.\n";
std::cin >> size;
int *arrPTR = new int[size]; // all news must be deleted!
// prefer pre-increment to post-increment where you can
for(int count(0); count < size; ++count)
{
std::cout << "Enter positive numbers to completely fill the array.\n";
std::cin >> arrPTR[count];
}
return arrPTR;
}
// passing size by value is fine (it may be smaller than pointer on some architectures)
void sortArray(int *arrPTR, int size)
{
// you may want to check if size >= 2 for sanity
// we do the two loops to avoid going out of bounds of array on last iteration
for(int i(0); i < size-1; ++i) // the first to compare (all except last)
{
for(int j(i+1); j < size; ++j) // the second to compare (all except first)
{
// do comparison
if (arrPTR[i] > arrPTR[j]) // from smallest to biggest (use < to go from biggest to smallest)
{
// swap if needed
int temp(arrPTR[i]); // put this on stack
arrPTR[i] = arrPTR[j];
arrPTR[j] = temp;
}
}
}
}
temp is a "pointer to int, which you're not initializing. When you say *temp = ... you're actually assigning to whatever temp happens to be pointing, but since you haven't told it what to point to, it can write pretty much anywhere in the address space of your program.
Because of the way you're using them, it seems that temp and swap shouldn't be pointers at all, just a plain int and bool.
You didn't initialize the temp pointer do when you dereference it you are writing to a random part of memory. Temp doesn't need to be a pointer, it can just be an int. Just replace EVERY instance of *temp with temp.