I recently learned about pointers, and have been working hard to really understand them. However, I have run into trouble. For class we had to write a function that would double an array x amount of times. I was able to write the function without any real problems, but I'm trying to implement it into an actual code and I continue to get invalid pointer errors. Here's the code:
#include <iostream>
using namespace std;
int *ArrayDoubling(int inputArray[], int initialSize, int numberToDouble);
int main(){
int arr[2] = {0,1};
int array_size = 2;
int number = 3;
ArrayDoubling(arr, array_size, number);
}
int *ArrayDoubling(int inputArray[], int initialSize, int numberToDouble){
for(int i=0;i<numberToDouble;i++){
int *array2 = new int[initialSize*2];
for(int i=0;i<initialSize;i++){
array2[i] = inputArray[i];
array2[i+initialSize] = inputArray[i]*2;
}
initialSize = initialSize*2;
delete []inputArray;
inputArray = array2;
}
return inputArray;
}
So what exactly is causing the problem, and how can I fix it? Also not sure if this will actually print the output of the Array, but I'm also trying to get that to happen. Thanks for any and all help!
The ArrayDoubling function calls delete[] on the inputArray argument. But you pass a pointer to an automatic array when you call it in main. Calling delete[] with a pointer that you didn't get from new[] has undefined behaviour.
To fix it, only use the function with dynamically allocated arrays.
Your inner loop is looping by the number of times to double, not the size of the array. For inputs where the size of the array is less than the number of times to double, you will be accessing out of range indices.
I am not quite sure what your intension is, but I think your second for loop should look like this:
for(int i=0;i<initialSize;i++)
The biggest problem with your code is this line: delete []inputArray;
inputArray was originally declared as int arr[2] = {0,1}; which should not be deleted. You can only delete variables which were created using keyword new.
Broadly speaking, your program is going to need to look something like this. Note that new[] happens outside of the population loops in ArrayRepeat so it is only called once and similarly delete[] will only be called once, on the same pointer that was created through new[].
// dynamically allocate an array which contains the first `N` elements of
// `array` repeated `repeats` times.
int * ArrayRepeat (int * array, size_t N, int repeats) {
int * result = new int[N * repeats];
assert(result); // Error check
// Loops to populate result goes here
return result;
}
int main (void) {
int arr[] = {0, 1};
int * repeated = ArrayRepeat(arr, 2, 3);
// Print the result
for (int i = 0; i < 2 * 3; ++i) {
printf("%d\n", repeated[i]);
}
delete[] (repeated);
return 0;
}
Related
i am trying to pass my array through my assign and draw functions. the assign function only exists to take the wins array and assign a value of 0 for all of the elements in the array. my draw function fills the array with random numbers 1-100 with 20 numbers in the array. when i try to compile i end up with a runtime error stating that the stack around my variable (array) wins is corrupted. where should i go from here?
#include<iostream>
#include <ctime>
using std::cout; using std::cin; using std::endl;
void draw(int a[]);
void assign(int a[]);
int sizeofarray = 20;
int main() {
int wins[20] = {};
assign(wins);
cout << "compiled!" << endl;
}
void assign(int a[20]) {
a[20] = {};
draw(a);
}
void draw(int a[])
{
srand(time(nullptr));
int rannum = (1 + rand() % 100);
for (int i = 0; i < 20; i++) {
a[i] = 1 + rand() % 100;
}
}
When you get an error with information as helpful as this, you should immediately be thinking "I have a buffer overflow". Then go looking for it.
Sure enough, here it is:
void assign(int a[20]) {
a[20] = {}; // <--- BOOM!
draw(a);
}
Your array can only store 20 elements. When you store something at the 21st element, you have undefined behavior.
Just adding some more information here. It's possible that you thought the offending line would zero-initialize the entire array (like it does when defining the variable). However, outside of an array definition, this is not the case. a[20] = {} is an assignment.
If you wish to zero the array, use std::fill as follows:
std::fill(a, a+20, 0);
I should point out, however, that there's no point zeroing the array in the context of your code as written. It's already zeroed on entry, and the draw function initializes every element anyway.
I am trying to code a class that represents a set of integers. It's a homework assignment but for the life of me I cannot figure out this issue.
In the class "IntSet", I have two private variables; one is a pointer to an array the other is the size of the array. I can create objects of this class and they work as intended. But I have this function named "join" that returns an object of the IntSet class. It essentially concatenates the arrays together then uses that array to create the returning object.
Here is my code:
#include <iostream>
using namespace std;
class IntSet {
int * arrPtr;
int arrSize;
public:
//Default Constructor
IntSet() {
int arr[0];
arrPtr = arr;
arrSize = 0;
}
//Overloaded Constructor
IntSet(int arr[], int size) {
arrPtr = arr;
arrSize = size;
}
//Copy Constructor
IntSet(const IntSet &i) {
arrPtr = i.arrPtr;
arrSize = i.arrSize;
}
/*
* Returns a pointer to the first
* element in the array
*/
int* getArr() {
return arrPtr;
}
int getSize() {
return arrSize;
}
IntSet join(IntSet &setAdd) {
//Make a new array
int temp[arrSize + setAdd.getSize()];
//Add the the values from the current instance's array pointer
//to the beginning of the temp array
for (int i = 0; i < arrSize; i++) {
temp[i] = *(arrPtr + i);
}
//Add the values from the passed in object's array pointer
//to the temp array but after the previously added values
for (int i = 0; i < setAdd.getSize(); i++) {
temp[i + arrSize] = *(setAdd.getArr() + i);
}
//Create a new instance that takes the temp array pointer and the
//size of the temp array
IntSet i(temp, arrSize + setAdd.getSize());
//Showing that the instance before it passes works as expected
cout << "In join function:" << endl;
for (int j = 0; j < i.getSize(); j++) {
cout << *(i.getArr() + j) << endl;
}
//Return the object
return i;
}
};
int main() {
//Make two arrays
int arr1[2] = {2 ,4};
int arr2[3] = {5, 2, 7};
//Make two objects normally
IntSet i(arr1, 2);
IntSet j(arr2, 3);
//This object has an "array" that has arr1 and arr2 concatenated, essentially
//I use the copy constructor here but the issue still occurs if I instead use
//Inset k = i.join(j);
IntSet k(i.join(j));
//Shows the error. It is not the same values as it was before it was returned
cout << "In main function:" << endl;
for (int l = 0; l < k.getSize(); l++) {
cout << *(k.getArr() + l) << endl;
}
return 0;
}
The program compiles and the output as of now is:
In join function:
2
4
5
2
7
In main function:
10
0
-2020743083
32737
-2017308032
I don't know why but the 10 and 0 are always the same every time I recompile and run. Also, if I print out the address of the pointer rather than the value(in both the join function and the main function), I get the same memory address.
Sorry if I misuse terms, I come from a java background, so pointers and such are a little new to me. If any clarification is needed, please ask.
Thanks in advance.
int temp[arrSize + setAdd.getSize()];
This is a local array, its lifetime ends once the function returned.
IntSet i(temp, arrSize + setAdd.getSize());
Here you are constructing an IntSet with this array. In fact the constructor simply changes a member pointer to the value of temp:
IntSet(int arr[], int size) {
arrPtr = arr;
arrSize = size;
}
As a result, since the lifetime of the object that temp and consequently also i.arrPtr is pointing to ends after leaving join, you will have a wild pointer. Dereferencing this pointer later in main invokes undefined behavior.
You need to allocate the array dynamically with new[] and delete it later with delete[]. The same goes for your constructors. Also note that if you use new[] in join and delete[] in the destructor, then you also have to make sure that the copy constructor actually copies the array (create new array with new[] and copy contents). If you simply assign the pointer then both the source and destination object will point to the same array and they will also both try to delete it at deconstruction, again invoking undefined behaviour.
But since this C++, you might as well use a std::vector which does all of this for you. (or std::set if you actually want a integer set)
The quickest fix with your code is to change
int temp[arrSize + setAdd.getSize()];
into this
int * temp = new int[arrSize + setAdd.getSize()];
The thing is that you allocated temp on the stack, so when join() returns that memory is releases. By allocating memory on the heap (as per the fix) the memory is not released when join() returns.
There are other things wrong with your code -- depending on the point of the assignment. I think most of these will be fixed when you consider the implications of having memory on the heap.
I'm trying to write code that has a pointer point to a 2-dimensional array.
My main purpose is for not just one asd array, like I would like to point 5 array each of which is 2 dimensional.
int asd1[2][2];
int asd2[2][2];
int *se;
se[0] = asd1;
se[1] = asd2;
Use se = asd[0];
The reason is that the symbol asd yields not a pointer to an int but rather a pointer to a one-dimensional array of ints.
#Mig's solution may be good, too. It depends on what you want. In my experience, it tends to work better when you treat a two-dimensional array of a basic type like int as though it were a one-dimensional of length n*n. (This is expecially true in numerical work, where you are likely to call BLAS and LAPACK, but may be true elsewhere, as well. You probably aren't doing numerical work here, but, well, try #Mig's and mine both, and see which you don't prefer. Good luck.)
You can do this:
#include<stdio.h>
int main()
{
int asd[2][2] = {{0,1},{2,3}};
int (*se)[2]; // a pointer (*se) to an array (2-element array, but only you know it, not the compiler) of array-of-two-integers [2]
se = asd;
printf("%d %d\n%d %d\n", se[0][0], se[0][1], se[1][0], se[1][1]);
return 0;
}
or:
#include<stdio.h>
int main()
{
int asd[2][2] = {{0,1},{2,3}};
int (*se)[2][2]; // a pointer (*se) to a 2-element array (first [2]) of two element array (second [2]) of ints
se = &asd;
printf("%d %d\n%d %d\n", (*se)[0][0], (*se)[0][1], (*se)[1][0], (*se)[1][1]);
return 0;
}
You want something like this:
int asd[2][2];
int (*se)[2] = asd;
This is equivalent to
int (*se)[2] = &asd[0];
because asd decays to a pointer to its first element in this context.
The key thing to bear in mind is that the type of asd[0] is int[2], not int*, so you need a pointer to an int[2] (i.e. int (*)[2]) and not a pointer to an int* (i.e. int**).
Incidentally, you can make an int* point to the first element of the asd[0] if you like:
int *p = &asd[0][0]; // or just = asd[0];, because it decays to &asd[0][0];
but accessing the other elements of the 2D array as if it were a 1D array, e.g. p[2], would be undefined behaviour.
As a more general point, it's often better to eschew using raw C-style arrays altogether if you can help it. You might want to investigate std::array or std::vector, depending on your needs.
If you were allocating that array dynamically, you could do something like this:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
int main() {
int i;
int **asd;
asd = (int **)malloc(sizeof(int *) * SIZE);
for (i = 0; i < SIZE; i++) {
asd[i] = (int*)malloc(sizeof(int) * SIZE);
}
int **se;
se = asd;
se[0][1] = 10;
printf("%d %d\n", se[0][1], asd[0][1]);
for (i = 0; i < SIZE; i++) {
free(asd[i]);
}
free(asd);
return 0;
}
EDIT: My first answer was wrong, here's what I had said:
You need a pointer to a pointer, since your array is 2-dimensional:
int asd[2][2];
int **se;
se = asd;
Now you should be able to:
se[0][1] = 10;
I am now starting Dynamic Memory Allocation in class and have a ok understanding of it but can't completely use it properly. I feel like I may not be so great with pointers either :p
My instructor gave instructions to create a function named readArray that will prompt the user for a number to use as a size to dynamically create a integer array of that size. I am then to assign the new array to a pointer. I then am supposed to prompt the user to fill the array. I then am supposed to return both the newly created array and the size.
I can not figure out how to return the array though, and I thought when dynamically allocating memory you were supposed to delete the allocation after using it to prevent leaks.
The array and size must be returned to main so I can pass it to other functions such as a sorting function.
I would greatly appreciate any help I can get as my thought process with this keeps going in the wrong direction.
#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;
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;
}
You would not need to do that if you use std::vector<int> which is far superior choice.
Use it:
std::vector<int> readArray()
{
int size = 0;
cout<<"Enter a number for size of array.\n";
cin >> size;
std::vector<int> v(size);
cout<<"Enter "<< size <<" positive numbers to completely fill the array : ";
for(int i = 0; i < size; i++)
{
cin>> v[i];
}
return v;
}
To return an array: declare readArray() as int* readArray() [return an int* instead of an int], and return arrPTR instead of size. This way, you return the dynamically allocated array which arrPTR points to.
Regarding the delete: When you are done using the array, you should indeed delete it. In your example, do it before return 0 in your main() function.
Make sure that since you allocated memory with new[], you should also free it with delete[], otherwise - your program will have a memory leak.
Like amit says, you should probably return the array instead of size. But since you still need the size, change readArray like so:
///return array (must be deleted after)
///and pass size by reference so it can be changed by the function
int* readArray(int &size);
and call it like this:
int size = 0;
int *arrPTR = readArray(size);
///....Do stuff here with arrPTR
delete arrPTR[];
After update:
int* readArray(int size); ///input only! need the & in the declaration to match
///the function body!
Is wrong, since you have your actual definition with the int &size.
You also don't declare arrPTR in readArray, just assign it.
i have created a map called select_p and vector of this map is called pts. i have stored data in a array and i want to pushbcak these data into my vector of map. i tried this by inserting value of array into new vector and then pushback into my map.but it is not working please help me to correct these codes? thanks
#include<iostream>
#include<cstdlib>
#include <map>
#include <vector>
using namespace std;
int main()
{
int M=7;
int N=6;
int i=0;
int * temp;
map<int,vector<int> > select_p;
vector<int>pts;
for (int m=0; m<M; m++)
{
for (int n=0; n<N; n++)
{
vector<int>id;
if (n==0 && m==5)
{
temp = new int[3,i+N,i+N+1,i+1];
unsigned ArraySize = sizeof(temp) / sizeof(int);
id.insert(id.begin(),temp[0], temp[ArraySize]);
select_p[i].push_back(id);
}
i++;
}
}
delete[] temp;
system("PAUSE");
return 0;
}
for (int m=0; m<M; m++) {
for (int n=0; n<N; n++) {
if (n==0 && m==5) {
Why are you looping when you only actually do anything for a single pair of values of m and n? The loops are completely useless here; you would get the same effect by just setting n = 0 and m = 5.
temp = new int[3,i+N,i+N+1,i+1];
Whatever you think this does, that's not what it does. This is equivalent to temp = new int[i+1];. The rest of the expression inside of the [] has no effect.
That said, you should not use new to create arrays in your program. Use std::vector; it is far easier to use correctly.
unsigned ArraySize = sizeof(temp) / sizeof(int);
This does not work. When you dynamically allocate an array, you are responsible for keeping track of how many elements are in it. Given a pointer to a dynamically allocated array (like temp here) there is no way to determine the number of elements in the array.
What you have is equivalent to sizeof(int*) / sizeof(int), which is not going to do what you expect.
id.insert(id.begin(),temp[0], temp[ArraySize]);
std::vector::insert takes a range of iterators: you have provided it with two values. Presumably you want to use temp, which points to the initial element of the dynamically allocated array, and temp + i + 1, which points one past the end of the array. That said, since you haven't set the values of the elements in the array, you are copying uninitialized memory, which probably isn't what you mean to do.
select_p[i].push_back(id);
select_p[i] is a std::vector<int>. std::vector<int>::push_back() takes a single int that is appended to the sequence. Presumably you just mean to use assignment to assign id to select_p[i].
You should get a good introductory C++ book if you want to learn to program in C++. I am sorry to say that your program is nonsensical.