Array of structs, unable to check if entry is NULL - c

Im toying with creating my own hash table data structure, but I have hit an unexpected problem, which I can't solve and haven't found a satisfying solution for it yet.
See, I have this linked list struct
struct Link
{
int v;
struct Link* next;
}
and then inside the hash table structure I want keep track of an array linked lists, like this:
struct Link** entries;
What I run into is, that for this to work, I first have to initialize the array like this:
entries = malloc(sizeof(struct Link*) * N);
for (i = 0; i < N; i++)
entries[i] = malloc(sizeof(struct Link));
What I want is not having to do the for loop that initializes the structs, because that's not how linked lists work, I want to leave entries[x] blank until it actually gets assigned a value.
If I don't do the for loop this happens:
if (entries[x] != NULL) /* true, the array is initialized */
entries[x]->v = value; /* SEGFAULT, there is no struct initialized */
That if statement 'should' return false if I haven't assigned a Link struct to it yet, but it doesn't.
One way of solving this problem is to just initialize all the first links of the linked list with that for loop and then checking for the value, but that's not what I want.
So does anyone know a way to solve this the way I want it to?

You can use calloc rather than malloc while allocating entries like:
entries = calloc(sizeof(struct Link*), N);

Well, you can't. Uninitialized pointers are not necessarily NULL.

You will need to initialize the pointer array after you allocate space for it with malloc(). You can use another for-loop like:
for (i = 0; i < N; i++)
{
entries[i] = NULL;
}
or simply use calloc() to allocate the array. This will set all elements to 0.
entries = calloc(N, sizeof(struct Link*));
Afterwards you need to allocate the elements as needed:
if (entries[x] == NULL)
{
entries[x] = malloc(sizeof(struct Link));
}
entries[x]->v = value;

Related

How to correctly free memory in a dynamic array inside an struct

I am struggling with the free of memory working with dynamic arrays. Considering the following code:
struct element{
float a;
float b;
};
struct list{
int size;
struct element *myelements;
};
int main(){
struct list mylist;
mylist.size = 0;
mylist.myelements = (struct element*) malloc(sizeof(struct element)*4); //I reserve it as if i had struct element myelements[4]
//i do stuff like
int i;
for(i = 0; i< 4 ; i++){
mylist.myelements[i].a = i;
mylist.myelements[i].b = i*2;
}
//I try to free myelements[2] for example, but i get an error
free(mylist.mylements[3]);
return 0;
}
My question is, how am i supposed to free the second possition of my array of elements. I have thought some alternatives involving realloc:
mylist.mybooks = realloc(mylist.mybooks, sizeof(mylist.mybooks) - sizeof(struct element));
but in that case wouldn´t I have to reorder the elements of the array?
Thanks in advance!
My question is, how am i supposed to free the second possition of my array of elements.
free deallocates the entire allocation done by malloc, it cannot deallocate a part of one allocation.
A common way to manage a resizeable array is to maintain its capacity and size, and when removing elements move subsequent array elements to fill the removed element gap and reduce the size. The spare capacity is used for new elements when they get inserted. Calling realloc for every element insertion/removal is sub-optimal in terms of speed.

Memory allocation of fixed size array inside a struct

I have the following tree node struct that holds pointers to other tree nodes:
struct node {
// ...
struct node* children[20];
}
The idea is that I want to check whether there is node* inside the children and based and that go deeper into the tree. So when I allocate the node I want to have children with 20 NULL values.
Currently I am not doin
How should I allocate this array in order to not get errors like Conditional jump or move depends on uninitialised value(s) (Valgrind)?
Would it be better to use struct node** children and allocate fixed size each time I allocate a new node?
EDIT: Example of one place where Valgrind complains:
for(int i=0;i<20;i++)
if(node->children[i] != NULL)
do_something_with_the_node(node->children[i]);
When you allocate a new instance of struct node, you must set the contained pointers to NULL to mark them as "not pointing anywhere". This will make the Valgrind warning go away, since the pointers will no longer be uninitialized.
Something like this:
struct node * node_new(void)
{
struct node *n = malloc(sizeof *n);
if(n != NULL)
{
for(size_t i = 0; i < sizeof n->children / sizeof *n->children; ++i)
n->children[i] = NULL;
}
return n;
}
You cannot portably use either memset() on n->children nor calloc(), since those will give you "all bits zero" which is not the same as "pointer NULL".
Your struct definition is valid (although it's hard to tell without more context if it fits your requirements).
Valgrind doesn't complain about your struct definition, it probably complains about how you instantiate variables of that type. Ensure that all of the array members get initialized and the complaints will most likely go away.
The problem is that you are using an unintialized value in an if condition.
When you instantiate a struct node, its member struct node* children[20]; is an array of 20 struct node *, all of which are uninitialized.
It would be no different from this:
char *x;
if (x == NULL) {
/* Stuff */
}
At this point, x may have literally any value. In your example, any element of an array may have any value.
To fix this, you need to initialize the elements of an array before using them, for example like this:
for (int i = 0; i < 20; ++i) {
node->children[i] = NULL;
}
Or shorter:
memset(node->children, 0, 20);
If you changed the member to, as you've suggested, node **children, the situation wouldn't be much different - you'll still need to initialize all the members, including array's elements. You could make it shorter by using calloc, which will initialize all bytes to 0; then again, you'll need some code for correct deallocation (and remember to do it), so I think the tradeoff's not worth it.

Global array for malloc

I am working on a project where I need to malloc some data. I am trying to reduce the heap peak of my program by changing around the main structure values I use. I am using a linked list. My struct is like:
struct myS{
int a,b;
float a,b;
struct myS *next;
};
I was thinking that instead of mallocing the struct pointer I would store it in a global array since I dont have much data. How would I do this ?
If you have upper bound for the number of elements you are going to need, you can create a global array [not dynamically allocated], let it be struct myS heap[], and an integer idx, initialized to 0. Once you allocate an element, you will need to increase idx, and attach this element to the requester.
Note - it is a good solution only if you are not expecting to delete elements [or you can afford to allocate each element only once].
If you do need delete, you will need to allocate an extra array that tells you which elements are currently in use, make idx circular [increase with idx = (idx + 1) % size], and check if each element is allocated before giving it, but as I say - it will probably be more time consuming!
code snap [not supporting deletes]:
struct myS heap[SIZE];
int idx = 0;
...
struct myS* allocate() {
return &(heap[idx++]);
}
Note: The above code snap is dangerous - it might overflow if you try to allocate more elements then you have in SIZE.
You could do something like this:
struct myS myArray[ARRAY_SIZE];
/* ... */
struct myS *head = &myArray[0];
head->next = &myArray[1];
head->next->next = &myArray[2];
/* etc... */
The array indexes used doesn't have to be sequential, e.g. head can be index 3 and head->next can be index 21
If you want to initialize the list to use all entries in the array at once, you could do it in a loop:
struct myS *node = head;
for (int i = 1; i < ARRAY_SIZE; i++)
{
node->next = &myArray[i];
node = &myArray[i];
}
node->next = NULL; /* Make sure the tail of the list doesn't have a 'next' pointer */

Am i using malloc properly?

Good day!
I need to use malloc in creating a student list system.... In order to be efficient, our professor asked us to use it on a struct so i created a struct as follows:
struct student {
char studentID[6];
char name[31];
char course [6];
};
struct student *array[30];
everytime i add a record, that is when i use malloc...
array[recordCtr]=(struct student*)malloc(sizeof(struct student));
recordCtr++;
then i free it like this.
for(i = 0; i < recordCtr; i++){
free(array[i]);
}
Am i using malloc properly??? what is the effect if i free it like this instead of the loop above.
free(array);
Thanks in advance. Your opinion will be highly appreciated.
You are doing fine.
free(array); would be undefined behavior because array itself was not allocated via malloc therefore you can't free it and don't need to - the memory will be managed by the compiler.
A good tip is to always do:
type *something;
something = malloc(n * sizeof(*something));
This is because, if you change the type of something, you don't have to change all sorts of other code. And sizeof is really a compiler operation here, it won't turn into anything different at runtime.
Also, don't cast the void* pointer returned by malloc, there's no reason to do so in C and it just further ties your code together.
So in your case, don't do:
(struct student*)malloc(sizeof(struct student));
but
malloc(sizeof(**array));
There is nothing illegal about the way you are using malloc but this isn't a list, it's an array of pointers.
To use a list you do not fix the size in advance and have a pointer to the next element. You can either make this intrusive of non-intrusive.
For an intrusive list you put struct student * next in the declaration of student.
For a non-intrusive list you create another struct student_list_node which contains an instance of struct student and a pointer struct student_list_node * next;
This is an exacmple of the non-intrusive version:
struct student_list_node
{
struct student data;
struct student_list_node * next;
};
struct student_list_node * head;
struct student_list_node * tail;
struct student_list_node * addStudentToTail()
{
struct student_list_node * newnode = (struct student_list_node *)(malloc( sizeof(struct student_list_node ) );
/* check malloc did not fail or use a checking vesrion of malloc */
if( !tail )
{
head = tail = newnode;
}
else
{
tail->next = newnode;
tail = newnode;
}
return newnode; // which is also "tail"
}
int main()
{
struct student_list_node * node = addStudentToTail();
struct student * pstud = &node->data;
/* write to pstud student details */
}
If you do really want to use an array, you might want to make it an array of student rather than student * in which case you can use calloc rather than malloc
struct student * array = (struct student *)calloc( 30, sizeof( student ) );
Then using free(array) would be the correct way to dispose of it. You also have the option of allocating more if you need it later with realloc. (Be careful with this one: you must keep a copy of your original pointer until you know realloc succeeds).
The array itself isn't allocated on the heap. Assuming it's a global variable, it is allocated in global memory at program startup and doesn't need to be freed. Calling free on it will probably corrupt your program.
Your current solution is correct.
What you're doing is correct.
You can think of *array[30] as an array of 30 pointers
When you are allocating memory for each of those pointers, you'd also need to call free() on each of them.
Yes, you are using it correctly. There are better ways to organize the storage than this, but this will work. At least until you need more than 30 students...
Note that you must call free() with each pointer that is returned by malloc(). That means that your loop over the array of pointers is the correct approach for your chosen architecture.
Your attempt to call free on the array itself will not work. It invokes Undefined Behavior because you are passing a pointer (to the base of the array itself) to free() that did not come from a call to malloc().
Looks fine.
You could (if it fits your problem) allocate space for all 30 structs in one go
struct student *array = (struct student *)malloc(30*sizeof(struct student));
whhen you want to dispose of the space, you can then do
free(array)
What you have will work just fine. As others have mentioned, you've created an array of pointers on the stack and need to malloc and free each of them individually as you are doing.
However, you don't have to use malloc and free one struct at a time, you can do something like this:
int arraySize = 30;
student * ourArray = (student*)malloc(sizeof(student) * arraySize);
and a single free on the pointer will take care of it. with this pointer, you can still use the bracket notation and the compiler will understand that it's a typed pointer and behave appropriately, giving you essentially the same thing. Which method you use depends on if you need your array a dynamic size or not as well as personal preference.
Hope that helps some.
Initialize your array of pointer to struct student with NULL values
for(i = 0; i < recordCtr; i++){
array[i] = NULL;
}
Free memory if array[i] is not NULL
for(i = 0; i < recordCtr; i++){
if(NULL != array[i])
{
free(array[i]);
}
}
There's simple rule: Every malloc() should be paired with free() with pointer returned by malloc. Not less, not more.

Failing to build a 'queue-like' structure - problems with struct declarations?

Hey guys. This is a very simple question, I'm sure, but I'm getting myself tangled up in C references/pointers as per usual. I am trying to build a... sort-of-queue, using a sort-of-linked list. Basically, I have a struct which has contents and a pointer to the next element. I also have a pointer to the first and last elements. I then have a loop that will be building the 'sort-of-queue'. My problem is that either my logic is failing and I'm not initialising the queue right, or my knowledge of C structs is failing (which is very probable) and I'm ending up just creating one struct and constantly referring to it.
My test code is as follows:
#include <stdio.h>
struct test {
int contents;
struct test *next;
};
main() {
struct test *first = NULL;
struct test *last = NULL;
int i;
for (i = 0; i < 2; i++) {
struct test tmp;
if (first == NULL) {
first = &tmp;
last = &tmp;
} else {
last->next = &tmp;
last = &tmp;
}
tmp.x = i;
tmp.next = NULL;
}
while (first != NULL) {
printf("%d\n", first->x);
first = first->next;
}
return 0;
}
Running this, I get the output that first seems to point to a test struct that has the value of '1' as it's 'x' variable - so not the initial one like I intended. So, am I failing at logic here, or am I failing at understanding how to declare new separate structs in a loop? Or maybe both? I'm very tired... >_<.
Thanks.
The problem you have is that you are taking the address of a temporary variable, tmp, and assigning it to a pointer which lives much longer than teh temporary, first and last. After every iteration of the loop the temporary is gone and continuing to access it via first and last results in undefined behavior.
You need to create a value on the heap in order to build up the list like so (error checking omitted for brevity)
struct test* tmp = malloc(sizeof(struct test));
Later though you'll need to go through and free all of the allocated nodes.

Resources