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.
Related
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;
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.
I am trying to set a value to array pointers and also set the pointers to NULL but when I try to run the program I am getting Segmentation fault (core dumped) and I believe it is because of what I have in the for loop. Please help
struct node {
int value;
node *next;
};
int main(){
node **adj;
int vert;
cout<<"Please enter the number of vertices: ";
cin>>vert;
adj = new node* [vert-1];
for (int x = 0; x <= vert-1; x++)//set all the names of the value.
{
adj[x]->value = x;
cout<< adj[x]->value;
adj[x] = NULL
}
return 0;
}
Using adj = new node* [vert-1]; just reserve memory for vert-1 pointers but, but you are assigning values to each of these pointers without reserving memory for them.
The correct way of doing what you want is:
node * adj;
..
adj = new node[vert-1]; // reserv memory for all information
// EDITED for out of array bounds: thanks #Leiaz
for (int x = 0; x < vert-1; x++)//set all the names of the value.
{
// now, you can modify a reserved memory portion
adj[x].value = x;
adj[x].next = NULL;
}
This is my structure which has two integer pointers aV and aT.
struct ADJP
{
int *aV;
int eV;
int nV;
int *aT;
int nT;
};
ADJP *Umb = NULL;
The allocation process of aV and aT is like this..
for(int i=0; i<nb; i++)
{
Umb[i].aV = new int[N];
for(int j=0; j<n; j++)
Umb[i].aV[j] = pIn[i].aV[j];
}
I want to remove one specific element from Umb array. for example I want to remove Umb[5], then how can I remove. I have tried with various mathods but got error due to allocated pointers I think. I have tried with follow method but its not working with this kind of struct array. It is working with struct array having no pointers.
int DeleteStructElement(int Index, ADJP *b, int N, int at)
{
for(int i=Index; i<N-1; i++)
memmove(&b[i], &b[i+1], (N-at-1)*sizeof*b); // moving the terms of array
N--; // updating new size
return N;
}
Have any idea how to remove an element from my struct array?
You will want to delete the arrays in the deleted element to release their memory:
delete[] b[Index].aV;
delete[] b[Index].aT;
Then, you only have to do a single memmove to remove the element.
memmove(&b[Index], &b[Index+1], (N-Index-1) * sizeof(b[Index])
EDIT: as Mahmoud points out, this doesn't use the at parameter in DeleteStructElement; I'm not sure what you intended that parameter to do.
int DeleteStructElement (int index, ADJP * b, int nb) {
delete [] (b[index].aV);
for (int i = index; i < nb - 1; ++i) {
b[i] = b[i+1];
}
return nb - 1;
}
Assuming you're really using C++, a destructor in ADJP would be much more straightforward than DeleteStructElement.
But if you're doing some interesting "C" with new/delete (perhaps a well-confined subset of C++?), then I'd suggest calling delete from within DeleteStructElement.
but got error due to allocated pointers I think
Answering this question might be much more important than others. I'm assuming this was a runtime error? Use a debugger to suss out just exactly where the fault was.
I'm quite sure this a simple issue, but I am trying to create a data structure that implements a dynamic array of structs.
Each struct will implement a linked list.
So I think that I want an array of pointers, which will point to the head of each list. For some reason, assigning method variables gives me a seg fault. I would love a little explanation of what I am doing wrong if you could. THANKS!
Oh, also, all of this is inside a class called Cache, so that is why there are some variables that don't appear to be defined, but I assure you they are. The program seg faults on indexes[i]->next = NULL; and the similar lines below that one.
typedef struct setNode {
char valid, dirty;
unsigned int tag;
setNode *next;
Cache *nextCache;
} set;
set **indexes;
arrayLength = cache_size / block_size;
indexes = new setNode *[arrayLength];
set *temp;
//Step through the array. The array is full of pointers to "Dummy Nodes"
for (size_t i = 0; i < arrayLength; i++) {
indexes[i]->next = NULL;
indexes[i]->valid = 0;
indexes[i]->dirty = 0;
indexes[i]->tag = 0;
//create empty linked list for each tag spot (One for direct mapped. etc...)
for(size_t i = 0; i < associativity; i++)
{
temp = indexes[i];
temp->next = new setNode;
temp = temp->next;
temp->next = NULL;
temp->valid = 0;
temp->dirty = 0;
temp->tag = 0;
}
}
}
indexes is an array of pointers to set objects, but they are uninitialized. They don't point to actual set objects, but merely to random memory locations. Trying to write to random memory is the very essence of the segmentation violation.
Before using your pointers, you need to allocate set objects and make the pointers point to them -- i.e.,
for (size_t i = 0; i < arrayLength; i++) {
indexes[i] = new set;
indexes[i]->next = NULL;
indexes[i]->valid = 0;
...