How do I properly reference this pointer multiple times? - c++

This is my function to find the union of 2 set arrays located by a void pointer which I have issues running the first part to copy Set A into the union Set before doing comparisons with Set B
Right now the output of this code produces example
Set A = {1,5,7,8}
Union Set = {8,8,8,8} Copies last element of Set A 4 times
as the last loop causes the temp pointer to point at 8.
Do I have to create a new int pointer for each loop or is there a better way of going around this
// Note I cannot use vectors or sorting methods as it isnt in my learning scope yet so i'll have to stick to the primitive comparison way
//Definitions
// VoidPtr is Void*
// aSet is (VoidPtr *a = new VoidPtr[MAX])
// getElementI(aSet[i]) Returns an integer value at that position of the pointer
void findUnion(VoidPtr * aSet,VoidPtr * bSet,VoidPtr * unionSet,int sizea,int sizeb,int &sizec)
{
int* temp;
VoidPtr vp;
int notEqual = 0;
// Copy set a into set c
for(int i =0; i < sizea; i++)
{
*temp = getElementI(aSet[i]);
vp = temp;
unionSet[i] = vp;
}
}

int* temp;
Here temp is an uninitiaised pointer
*temp = getElementI(aSet[i]);
Here temp is being dereferenced. Dereferencing uninitialised pointers results in a program crash (at best) and all sorts of weird behaviour (at worst).
I'm finding it quite hard to understand what you really need to do, but allocating a new int pointer every time round the loop sounds reasonable. Like this
for(int i =0; i < sizea; i++)
{
int *temp = new int (getElementI(aSet[i]));
unionSet[i] = temp;
}
But I am guessing.

Related

for Loops in C++ with Arrays and Pointers

My teacher introduced us to looping through an array in the following format:
int size;
cin >> size;
int *garbage = new int[size];
for (int* p = garbage; p < (garbage + size); p++) {
if (*p > *max) {
max = p;
}
}
I understand what's going on, but it's just odd to me as a new concept. Are there better ways of going through an array like this?
Second Question: do you have to turn every pointer to a nullptr once you are done with it? For example, does it cause memory leaks to have that for loop like that with the pointer p or does it self destruct once it leaves the for loop scope?
There certainly are better (as in - more readable) ways of iterating through an array. For instance:
for (int index = 0; index < size; index++) {
if (p[index] > *max) {
max = &p[index];
}
}
However, as you see in the max = ... assignment, it's easier to have a pointer to an element of an array if you want to pass it on to another pointer variable.
Regarding your second question - there is no inherent value in setting it to nullptr. However, to prevent memory leaks, you should deallocate (free) the memory you reserved with operator new by using the operator delete once you're done with the array, like so:
delete [] p;
EDIT: Please note that you won't be able to safely dereference the pointer max (meaning you can't read that int it's pointing to with *max expression) after you deallocate the array without causing Undefined Behavior and possibly crashing your program, because your program will return the reserved memory to the OS and won't have access to it.
Thanks to #user4581301 for pointing it out.
There's another way of solving the problem. There's a C++ standard library algorithm for finding the maximum element in a range: std::max_element. No hand-written loop is needed.
int max = *std::max_element(garbage, garbage + size);
Note that it returns an iterator (a pointer in this case) so I used * to get the value from the iterator.
Your teacher might not like this solution.
It's a bit cleaner to do this:
int size = 10, max = 0;
int *mem = new int[size];
int *end = mem + size;
for (int *p = mem; p < end; p++)
if (*p > max)
max = *p;
But if you start using C++11 you can do this:
int max = 0;
std::vector<int> mem;
for (auto &i : mem)
if (i > max)
max = i;
There are probably even easier ways using other std namespace tools.
do you have to turn every pointer to a nullptr once you are done with it?
No, but it helps a lot when debugging. If you use a freed pointer that wasn't set to nullptr you'll be a lot more confused than if it is nullptr. Setting the pointer to nullptr doesn't actually automatically free the memory. You still have to call the appropriate 'free' function before setting to nullptr.
in C++11 you can do this:
int max = 0;
std::vector<int> mem;
for (auto &i : mem)
if (i > max)
max = i;

Memory write exception when creating a graph

I am working on a program on C++ that's dealing with graphs.
I store graph as an adjacency list of nodes, and I have the corresponding structures declared in .h file as follows:
typedef struct Node {
int val;
struct Node * next;
} node;
typedef struct Graph {
int v;
node ** arr;
node ** arr2; // reserved list for a reversed directed graph.
} graph;
I have a function for initializing a graph defined as follows:
graph * creategraph(int v) { // v == number of vertices
int i;
graph * temp = (graph*)malloc(sizeof(graph));
temp->v = v;
for(i = 0; i < v; i++) {
temp->arr = (node**)malloc(v*sizeof(node*));
}
for(i = 0; i < v; i++) {
temp->arr[i] = NULL;
}
return temp;
}
I call the function as shown below to create a graph with number of vertices being equal to num_vertices:
graph * g = creategraph (num_vertices);
With num_vertices being equal to 200000, the "Access Violation Writing Location" exception is raised in graph * createGraph on the first execution of temp->arr[i] = NULL;.
Could anyone tell me what's the problem here? Thank you.
Here is a big problem:
for(i = 0; i < v; i++) {
temp->arr = (node**)malloc(v*sizeof(node*));
}
This allocates space for v nodes, but you only have a pointer to the last one you allocated. This is a memory leak. What you need to do is this:
temp->arr = (node**)malloc(v*sizeof(*temp->arr));
for(i = 0; i < v; i++) {
temp->arr[v] = (node*)malloc(sizeof(*temp->arr[0]));
}
Explanation:
arr is pointer to pointer to Node. First we need to allocate memory for v pointers. Then we need to allocate memory for a Node for each of these pointers.
Also note that it is unnecessary (and therefore bad) to cast malloc in C. If you're coding C++ it is necessary, so if you code "C" but are using a C++ compiler, you will need to cast the result.
Sidenote:
It's good practice to write int arr = malloc(n*sizeof(*arr)) or int arr = malloc(n*sizeof(arr[0])) instead of int arr = malloc(n*sizeof(int)). The reason is that if you in the future decides that you want to use long instead of int you will not have to change it on more than one place.
The problem is that you're needlessly allocating temp->arr v times, and leaking all of the previous allocations, so you use v times as much memory as you need to. You only need to allocate it once, so get rid of the loop.
Don't cast the return value of malloc(), while you're at it.

How do pointers work

Here is simple code I'm asking my questions about.
struct Class{
public:
int key;
Class*next;
};
int main(){
Class c;
c.key = 1;
Class* p = &c;
for (int i = 2; i < 5; i++){
Class next;
next.key = i;
p->next = &next;
p = p->next;
}
p = &c;
for (int i = 1; i < 5; i++){
std::cout << p->key;
p = p->next;
}
}
Output I was expecting: 1234
Output I've got: 1444
Can you, please, tell me what is wrong with my code, and what do I have to do to get 1234.
for (int i = 2; i < 5; i++){
Class next;
next.key = 2;
p->next = &next;
p = p->next;
}
The lifetime of the next object ends at the end of each iteration. Since you're assigning the address of this object to p->next, this pointer is left dangling when the iteration ends. In the next iteration, when you attempt to use p, you are invoking undefined behaviour.
Your logic seems correct but as the other commentators pointed out the variables created inside a loop are local to that loop so expire as soon as you are out of the loop. You need a minor modification.
Alternate solution: Just replace your first loop with:
for (int i = 2; i < 5; i++){
p->next = new Class;
p->next->key = i;
p = p->next;
}
This will allocate required memory and create a new entry at each iteration.
Hope that helps!
To explain Chris' comment - accessing a variable outside of its scope is undefined behavior. Your next variable's scope is one iteration of the for loop, once you have reached the closing } for the loop (and i++ has run, I think), it is up to the compiler to deal with deallocating the memory for next, and then reinitializing it next run. Your compiler appears to be making the reasonable decision to keep next in the same piece of memory and run the constructor again on each iteration, which is why your memory access is not throwing segmentation faults (IE, trying to access memory your program hasn't been granted access to). Your compiler could also decide to deallocate next as soon as you exit the for loop, but also doesn't appear to be doing that, which is why you are able to access its memory to print.
Long story short, don't worry too much about figuring out why your program does what it does, instead use heap memory as shown by kvorobiev, which will persist past the end of the for loop's scope. As good practice, you should also delete the memory once you are done wit it.
The problem is that inside this loop
for (int i = 2; i < 5; i++){
Class next;
next.key = 2;
p->next = &next;
p = p->next;
}
for each its iteration you are using the same local variable. Thus for the second iteration of the loop p->next points to the same local object.
So your porgram has undefined behaviour because this local object is not alive after exiting the loop. In general case the memory occupied by the local variable can be overwritten.
It seems that as result you have to nodes. One is c that points to already "died" node next and the died node next that points to itself and keeps the last value that was stored in data member key that is 4.
You should either dynamically allocate each node or use an array of nodes of the list.
Here is a demonstrative program that shows how you could use a simialr approach by means of an array.
#include <iostream>
struct Class
{
public:
int key;
Class *next;
};
int main()
{
const size_t N = 4;
Class c[N];
c[0].key = 1;
Class *p = &c[0];
for ( size_t i = 1; i < N; i++ )
{
c[i].key = i + 1;
p->next = &c[i];
p = p->next;
}
p = &c[0];
for ( int i = 0; i < N; i++ )
{
std::cout << p->key;
p = p->next;
}
std::cout << std::endl;
return 0;
}
The output is
1234

C++: The value that the pointer is pointing to changes

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.

Unitialized local variable and help correcting

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.