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;
...
Related
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 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.
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
I have a dynamically allocated array of polymorphic objects that I would like to resize without using STL library (vectors, etc). I've tried moving the original to a temporary array, then deleting the original, then setting the original equal to the temporary, like this:
int x = 100;
int y = 150;
Animal **orig = new Animal*[x];
Animal **temp = new Animal*[y];
//allocate orig array
for(int n = 0; n < x; n++)
{
orig[n] = new Cat();
}
//save to temp
for(int n = 0; n < x; n++)
{
temp[n] = orig[n];
}
//delete orig array
for(int n = 0; n < x; n++)
{
delete orig[n];
}
delete[] orig;
//store temp into orig
orig = temp;
However, when I try to access the element for example:
cout << orig[0]->getName();
I get a bad memeory alloc error:
Unhandled exception at at 0x768F4B32 in file.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0033E598.
//delete orig array
for(int n = 0; n < x; n++)
{
delete orig[n];
}
For this particular case, don't do this. You are actually deleting the objects not the array. So all the objects in the temp array are pointing to invalid locations. Simply do delete [] orig to deallocate the original array.
You are copying wrong. Instead of copying your temp array is simply pointing to the same location as that of the orig. Now when you delete the orig the temp pointers point to an invalid location.
//save to temp
for(int n = 0; n < x; n++)
{
//temp[n] = orig[n];
// Try this instead
strcpy(temp[n], orig[n]);
}
I have an array of pointers of CName objects. I have the following constructor which initializes my array to size one. Then when I add an object I grow the array by 1 and add the new object. It compiles fine, however when I try to print them I just get segmentation fault error. Can you look and see if I'm doing anything wrong?
//constructor
Names_Book::Names_Book()
{
grow_factor = 1;
size = 0;
cNames = (CName**)malloc(grow_factor * sizeof(CName*));
cNames[0] = NULL;
}
void Names_Book::addCName(CName* cn)
{
int oldSize = size;
int newSize = size + 1;
CName** newCNames = (CName**)malloc(newSize * sizeof(CName*));
for(int i=0; i<newSize; i++)
{
newCNames[i] = cNames[i];
}
for(int i=oldSize; i<newSize; i++)
{
newCNames[i] = NULL;
}
/* copy current array to old array */
cNames = newCNames;
delete(newCNames);
size++;
}
To have dynamically growable array in C++, you should use std::vector or at least look at its implementation.
There are a few things wrong with this function:
void Names_Book::addCName(CName* cn)
{
int oldSize = size;
int newSize = size + 1;
CName** newCNames = (CName**)malloc(newSize * sizeof(CName*));
for(int i=0; i<newSize; i++)
{
newCNames[i] = cNames[
}
for(int i=oldSize; i<newSize; i++)
{
newCNames[i] = NULL;
}
/* copy current array to old array */
cNames = newCNames; //right here you just leaked the memory cNames was pointing to.
delete(newCNames); // right here you delete the new array you just created using the wrong call.
size++;
}
Near the end you do two things quite wrong. (Commented above.)
Those last two lines should be:
free(cNames);
cNmaes = newCNames;
Also, you should do a realloc rather than slowly copying elements one by one....
With that said, you should use vector.
Don't try to (poorly) rewrite what already exists.
The first loop should be to oldSize:
for(int i=0; i<oldSize; i++)
cNames isn't big enough for newSize.