Freeing a dynamically allocated structure instance in C - c

I have following structure:
typedef struct generic_attribute_struct{
attribute_value current_value;
attribute_value previous_value;
attribute_value running_value;
} generic_attribute;
where attribute_value is simply a placeholder for unsigned long long int.
I have the following constructor for this structure:
generic_attribute* construct_generic_attribute(attribute_value current_value){
generic_attribute *ga_ptr; //allocate space for pointer to generic attribute
if(ga_ptr = malloc (sizeof (generic_attribute))){ //if allocation succeeds
set_ga_current_value(ga_ptr, current_value); //assigned the current value to given input
set_ga_previous_value(ga_ptr, 0); //set previous value to zero
set_ga_running_value(ga_ptr);
} else{ //else, inform user of error
fprintf(stderr, "Health Monitor ran out of space when allocating memory for a generic attribute.");
}
return ga_ptr; // return pointer to new attribute or a NULL pointer if memory allocation failed
}
where set_ga_running_value looks like this:
attribute_value set_ga_running_value(generic_attribute* ga_ptr){
attribute_value delta = get_ga_current_value(ga_ptr) - get_ga_previous_value(ga_ptr);
ga_ptr->running_value = (ga_ptr->running_value? ga_ptr->running_value : 0) + delta;
return ga_ptr->running_value;
}
Destructor for this structure looks like this:
void destroy_generic_attribute(generic_attribute** ga_ptr){
free(*ga_ptr);
}
I created a test that asks the user for some current_value input, constructs a pointer, and prints out whether the values for structure variables are what they ought to be. This test loops until the user no longer wants to test, in which case they quit out of the test.
So, the test looks like this:
Does user want to test? If yes, go to 2). If no, go to 7).
Get input from user
Call constructor for generic attribute with this new input
Verify that generic attribute was created correctly
Call the destructor on generic attribute
Go to 1.
Quit
This is what the test looks like:
void test_generic_attribute_constructor_with_user_input(){
attribute_value input;
int continue_var;
bool current_value_test, previous_value_test, running_value_test, pointer_test;
generic_attribute* ga_ptr;
while(1){
printf("Would you like to execute a test for Generic Attribute Constructor? Type 1 for YES, or 0 for NO: ");
scanf("%i", &continue_var);
if(continue_var){
printf(TESTING, "Constructor for Generic Attribute and Generic Attribute Reader");
printf("\n" INPUT, "single number");
scanf("%lld", &input);
ga_ptr = construct_generic_attribute(input);
read_generic_attribute(ga_ptr);
current_value_test = (get_ga_current_value(ga_ptr) == input ? true : false);
previous_value_test = (get_ga_previous_value(ga_ptr) == 0 ? true: false);
// THIS TEST FAILS
running_value_test = (get_ga_running_value(ga_ptr) == input ? true: false);
pointer_test = (ga_ptr ? true: false);
printf("%s.\n", ((current_value_test && previous_value_test && running_value_test && pointer_test) ? PASS : FAIL));
destroy_generic_attribute(&ga_ptr);
}else{
printf("\nOK! Testing concluded.");
break;
}
}
}
My problem is that the "running value" seems to never get "reset" when the ga_ptr gets destroyed. It seems to keep its old value. How would I clear memory for the entire ga_ptr structure properly?
test result:
Would you like to execute a test for Generic Attribute Constructor? Type 1 for YES, or 0 for NO: 1
Testing Constructor for Generic Attribute and Generic Attribute Reader:
Please enter single number for input: 10
Generic Attribute has the following contents:
Pointer Current Value Previos Value Running Value
0x600058530 10 0 10
PASS.
Would you like to execute a test for Generic Attribute Constructor? Type 1 for YES, or 0 for NO: 1
Testing Constructor for Generic Attribute and Generic Attribute Reader:
Please enter single number for input: 20
Generic Attribute has the following contents:
Pointer Current Value Previos Value Running Value
0x600058530 20 0 30
FAIL.
I would expect the Running value to be 20.
If I change the destructor to this:
void destroy_generic_attribute(generic_attribute** ga_ptr){
set_ga_current_value(*ga_ptr, 0);
set_ga_previous_value(*ga_ptr, 0);
(*ga_ptr)->running_value = 0;
free(*ga_ptr);
}
My test pass... However, I do not understand why skipping the setters makes the code fail.

You are just invoking undefined behaviour by using a never initialized value.
In construct_generic_attribute, you initialize current and previous value and then call set_ga_running_value. In the latter, you use current and previous values that have just been initialize to compute delta : fine until here. But then you have :
ga_ptr->running_value = (ga_ptr->running_value? ga_ptr->running_value : 0) + delta;
Meaning that you use running_value before initializing it. As it is in a freshly malloc'ed struct, its value is just undefined. It might be 0, or it might be the value that existed in this memory location before allocation, or it might be a special value that compiler uses as a special initialization : you cannot know and should not rely on anything.
You compiler seems to preinitialize memory to 0 on run and then never change the value on free and malloc, giving 30 on second run. Mine (in debug mode) allways initialized malloc'ed values to 0xcdcdcdcd, giving FAIL on each test. Just undefined behaviour ...
So you really should initialize the freshed allocated struct in your constructor :
if(ga_ptr = malloc (sizeof (generic_attribute))){ //if allocation succeeds
memset(ga_ptr, 0, sizeof(generic_attribute)); // ensure all values are set to 0
set_ga_current_value(ga_ptr, current_value); //assigned the current value to given input
set_ga_previous_value(ga_ptr, 0); //set previous value to zero
set_ga_running_value(ga_ptr);
or if you know that running_value is an integral, just replace the memset with:
ga_ptr->running_value = 0;

Related

What is wrong with my insert function for min-heaps?

I'm trying to write a minimum heap data structure in C, but I ran into some issues while implementing the insert function.
It looks like this :
void insert(MinHeap* minh , int key)
{
if(minh->itemcount == minh->maxSize)
{
printf("cant insert,heap is full\n");
return;
}
minh->itemcount++;
minh->HeapArray[minh->itemcount]=key;
int parent=getParent(minh->itemcount);
while(parent != 0 && minh->HeapArray[parent] > minh->HeapArray[minh->itemcount])
{
swap(&(minh->HeapArray[parent]), &(minh->HeapArray[minh->itemcount]));
parent = parent/2;
}
}
Now the insertion process works if I insert the following values:
insert(minheap,5);
insert(minheap,3);
insert(minheap,2);
insert(minheap,4);
The output came out to be:
2 4 3 5
This is a valid output, since it follows the minimum heap property.
But once I start adding more values like 1, the output is:
2 1 3 5 4
As can you see, there is "bubbling up" of 1 occurring, but it doesn't seem to go all the way up, since 1 should be the first element, not 2.
I'm not sure why is this occurring, because my code for insertion has the same logic as any other minimum heap insertion function.
It would be great if anyone can help with clearing this up.
Some side notes:
MinHeap is a type-defined structure, and its members are :
typedef struct Heap
{
int* HeapArray;
int maxSize;
int itemcount;
} MinHeap;
I have a created an "instance" (with malloc) of this structure in the main function. I also dynamically allocated memory for the HeapArray Member. I also set the itemcount member to be equal to 0.
Also, the indexing for my minimum heap array starts with 1 not 0,
so the getParent function returns the following:
int getParent(int index)
{
return floor(index/2);
}
The main issue is that you are always swapping with the same element, i.e. with the last one at minh->HeapArray[minh->itemcount]: in the first iteration of the loop this is indeed the child of parent, but if there are more iterations, it no longer represents the child.
As a side issue: you have parent = parent / 2 in your loop: why didn't you use the getParent function here?
Secondly, the getParent function does not need to use floor: the division is already an integer division.
Here is the correction of where the main issue occurred:
int child = ++minh->itemcount;
minh->HeapArray[child] = key;
int parent = getParent(child);
while (parent != 0 && minh->HeapArray[parent] > minh->HeapArray[child]) {
swap(&(minh->HeapArray[parent]) , &(minh->HeapArray[child]));
child = parent;
parent = getParent(child);
}

C struct instance overwrites previous instance

I'm new to C, so the answer might be obvious but I just can't get my head around it.
I'm trying to create C++ vector kind of structure in C. I use Windows EnumWindows function to loop through all the windows. In the callback function I create new instance of windowHandle -structure for each window. For some reason however it doesn't seem to create new instance but rather just overwrites the old one. Or maybe it creates new instance, but when I give value to attribute windowHandle->title, it applies that change to every instance of windowHandle?
Callback function:
BOOL CALLBACK delegate(HWND wnd, LPARAM param){
if (filter(wnd)){ //<- just to make sure it's kind of window that we want.
char windowName[256] = {};
GetWindowText(wnd, windowName, sizeof(windowName));
windowHandle *handle = malloc(sizeof(windowHandle)); //<- create new instance of windowHandle for each window
handle->hWND = wnd;
handle->title = windowName;
insert((windowArray*) param, handle); //<- insert each windowHandle in our 'vector'
}
// but return true here so that we iterate all windows
return TRUE;
}
Call to EnumWindows function:
windowArray* array = array_init(20);
EnumWindows(&delegate, (LPARAM) array); //<- not quite sure what that '&'-sign does?
Structures:
typedef struct windowHandle{
HWND hWND;
char* title;
} windowHandle;
typedef struct windowArray{
int count;
int capacity;
int objectSize;
windowHandle* windows;
} windowArray;
And lastly insert:
int insert(windowArray* array, void* handle){
int index = (array->count * array->objectSize);
if(index > 0){
printf("\n%s %s\n", "first element's title is: ", array->windows->title); //<- prints to see if new handle overwrite the previous ones
}
printf("%s %s %s %p %s %d\n", "Inserted element ", ((windowHandle*)handle)->title, " with pointer ", handle, " on index ", index);
fflush(stdout); //<- prints info about first & current window
memcpy(array->windows + (index), (windowHandle*)handle, array->objectSize);
array->count++;
}
Output during insert calls:
Inserted element joo - Java - nativeWindowCapture/src/NativeWindowHookImp.c - Eclipse SDK with pointer 0000000000FB1B90 on index 0
first element's title is: Komentokehote
Inserted element Komentokehote with pointer 0000000000FB1BB0 on index 16
first element's title is: C struct instance overwrites previous instance - Stack Overflow - Mozilla Firefox
Inserted element C struct instance overwrites previous instance - Stack Overflow - Mozilla Firefox with pointer 0000000000FB1BD0 on index 32
first element's title is: JNI compiler kutsu – Muistio
Inserted element JNI compiler kutsu – Muistio with pointer 0000000000FB1BF0 on index 48
first element's title is: Skype™?
Inserted element Skype™? with pointer 0000000000FB1C10 on index 64
first element's title is: eclipse
Inserted element eclipse with pointer 0000000000FB1C30 on index 80
first element's title is: src
Inserted element src with pointer 0000000000FBCCE0 on index 96
all added
and then if I print the full content of windowArray->windows, I get the following results:
Getting value src , at index 0 and pointer 0000000000FBBB80
Getting value src , at index 16 and pointer 0000000000FBBC80
Getting value src , at index 32 and pointer 0000000000FBBD80
Getting value src , at index 48 and pointer 0000000000FBBE80
Getting value src , at index 64 and pointer 0000000000FBBF80
Getting value src , at index 80 and pointer 0000000000FBC080
Getting value src , at index 96 and pointer 0000000000FBC180
P.S. I would also like to know why windowArray's windows-attribute's pointers are different from those of *handle-objects created in delegate? That doesn't seem to be very efficient memorywise?
You set handle->title to point to windowName. But as soon as you exit this scope, windowName will cease to exist. So your structure contains a pointer to an array that no longer exists.
char windowName[256] = {};
GetWindowText(wnd, windowName, sizeof(windowName));
windowHandle *handle = malloc(sizeof(windowHandle)); //<- create new instance of windowHandle for each window
handle->hWND = wnd;
handle->title = windowName;
}
// when we get here, windowName ceases to exist
// so why did we store a pointer to it?
After you exit the scope, it is an error to follow the title pointer, since it no longer points to any object that is still alive. Perhaps change title from char * to char[256].

How to cancel second function only if first function executes in C?

The two functions are about 200 lines since its a bunch of case statements (and they do work properly) so instead of showing I'll just explain what it does. I am currently creating a game similar to checkers.
Function 1: Checks if user input a valid move. If they did not then it would print out "invalid move".
Function 2: Updates the piece that has been moved on the board and displays the new updated board.
In the main function I did a while loop so if user input an invalid move, they will be prompted again. It does that but the board would still be updated. For example: if they chose to move piece 1 to a spot that piece 3 is occupying, the board will update: piece 1's spot is now empty even though it printed out "invalid move". I do not know how to stop function 2 if function 1 printed something.
Here is what I put in the main function.
char pieceToMove, emptySpot;
int moveNumber = 0;
int piecesOnBoard = 15;
while (piecesOnBoard >= 1, ++moveNumber) {
//prompting user input
printf("%d. Enter your move:", moveNumber);
scanf(" %c %c", &pieceToMove, &emptySpot);
checkMoves(pieceToMove, emptySpot, all, the, pieces, ect);
updateBoard(all, the, pieces);
}
Have function 1 return the equivalent of a Boolean value (1 or 0 — true or false, respectively, in C) depending on whether function 1 was successful or if it failed. Check that value before deciding to run function 2 (or not).
One way to do this is define a boolean_t convenience type and kTrue and kFalse values in your header file. These are int values underneath the hood, but this makes code easier to read:
typedef enum boolean {
kFalse = 0,
kTrue
} boolean_t;
In your header file, declare that your first function function_one() will return a boolean_t:
boolean_t function_one(...); /* "..." are the arguments this function takes */
In your implementation file, you write function_one() so that it returns either kTrue or kFalse, depending on whether its work succeeds or fails:
boolean_t function_one(...) {
do_stuff();
if (some_step_fails) {
return kFalse;
}
return kTrue;
}
Again in the implementation file, write the call to function_two() so that it runs only if the return value of function_one() was kTrue:
if (function_one(...) == kTrue) {
function_two();
}
else {
fprintf(stderr, "Error: Something went wrong...\n");
}

Behaviour of an hashtable using glib

I want to update the Volume to each #IP. So that for example after each 5 s I add V(i) of each #IP(i). Ok Now the hash table works fine it keeps updated after every T seconds. But the problem is that after a certain period I find that sometimes the same ip adress is repeated twice or even a lot of times within the hash table. So that when I close the process I find the same #IP repeated too many times. It is like there is a problem with the hash table or something like that.
Here is the code this funcion "update_hashTable()" is so important it is called every X seconds I suspect in fact a memory leak ... because I always call malloc for IP#.
but it keeps working ... any idea ???
int update_hashTable( ... ) {
u_int32_t *a;
... //declarations
struct pf_addr *as;
as = ks->addr[0];
a = (u_int32_t*)malloc(sizeof(u_int32_t));
*a = ntohl(as->addr32[0]);
sz = value; // no matter it is... an int for example
if (ReturnValue=(u_int32_t)g_hash_table_lookup(hashtable, a)) {
ReturnValue +=sz;
g_hash_table_insert(hashtable, (gpointer)a, gpointer)ReturnValue);
}
else {
g_hash_table_insert(hashtable, (gpointer)a, (gpointer)sz);
}
Indeed, you appear to have a memory leak, but this isn't your problem. The problem is that the true-path of your if statement simply reinserts a second value associated with the same key, which is not what you want.
The typical pattern for this check-if-exists and increment algorithm is usually something like
gpointer val = g_hash_table_lookup(hash_table, key);
if (val == NULL) {
val = g_malloc0(...);
g_hash_table_insert(hash_table, key, val);
}
*val = /* something */;
The important thing to take away from this is that once you have a pointer to the value associated with some key, you can simply modify it directly.
If this code will be executed by multiple threads in parallel, then the entire block should be protected by a mutex, perhaps with GMutex: http://developer.gnome.org/glib/2.28/glib-Threads.html
gcc provides atomic builtin intrinsics, say for atomically incrementing the value, see http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html

Variable Persistence in Linked List

I'm making a domino game and when the user adds a domino to the left, the domino is added but when the function exits the domino added is GONE.
FYI:
fitxesJoc (Link List) contains the dominoes of
the game and is a pointer passed to the function (so that it lasts all the game)
opcionesCorrectas (Domino) contains the correct choices of domino
inferior (int) contains the smaller number of the domino
superior (int) contains the bigger number of the domino
pos (int) the position of the domino
opcionFitxa (int) contains the choice of the player
ultimaFitxa->seg is the 'next' node
tNode* ultimaFitxa = (tNode *)malloc(sizeof(tNode));
ultimaFitxa->info.inferior = opcionesCorrectas[opcionFitxa - 1].inferior;
ultimaFitxa->info.superior = opcionesCorrectas[opcionFitxa - 1].superior;
ultimaFitxa->info.pos = opcionesCorrectas[opcionFitxa - 1].pos;
ultimaFitxa->seg = fitxesJoc;
fitxesJoc = ultimaFitxa;
Header of the function
unsigned int demanar_fitxa_tirar(tJugador *jugador, tNode* fitxesJoc, tPartida *partida, tPila* fitxesBarrejades, bool primerCop)
Call of the function
resultado = demanar_fitxa_tirar(&Jugadors[jugadorActual], fitxesJoc, partida, fitxesBarrejades, true);
This way I add the domino, in the top of the other dominoes.
Your problem is that the last line of demanar_fitxa_tirar:
fitxesJoc = ultimaFitxa;
is assigning to a local variable, which has no effect on the calling code. You need to pass a pointer to the calling code's fitxesJoc, like this:
unsigned int demanar_fitxa_tirar(..., tNode** fitxesJoc, ...) // Note extra *
{
// ...
*fitxesJoc = ultimaFitxa; // Note extra *
}
void mainProgram()
{
tNode* fitxesJoc;
// ...
resultado = demanar_fitxa_tirar(..., &fitxesJoc, ...); // Note extra &
// ...
}
From your code, it's not clear where your function starts and ends and what it takes as parameters but I guess your problem is with the fitxesJoc variable which is probably passed as an argument to the function. C copies arguments when calling functions (call-by-value). You could pass the address to fitxesJoc variable using a pointer instead and rewrite it as something like this:
// fitxesJoc would be a `tNode**` rather than `tNode*`.
tNode* ultimaFitxa = (tNode *)malloc(sizeof(tNode));
ultimaFitxa->info.inferior = opcionesCorrectas[opcionFitxa - 1].inferior;
ultimaFitxa->info.superior = opcionesCorrectas[opcionFitxa - 1].superior;
ultimaFitxa->info.pos = opcionesCorrectas[opcionFitxa - 1].pos;
ultimaFitxa->seg = *fitxesJoc;
*fitxesJoc = ultimaFitxa;
I don't think you've provided enough code, but I suspect the problem is in:
fitxesJoc = ultimaFitxa;
(Linked-list now equals the new Node).
The problem is that parameters are passed by value.
If you want to change the value of the parameter, you'll need to pass by pointer,
and use the pointer to change the value.
*pfitxesJoc = ultimaFitxa;
Please provide more code, including the function header and the function call, for a better answer.
It looks like you're not actually adding the new domino to the linked list. But, it's hard to tell because you need to post more code, and because your code isn't in English.

Resources