What does void (*var)(void*) in an argument mean? [duplicate] - c

This question already has answers here:
How do function pointers in C work?
(12 answers)
Closed 1 year ago.
I am doing a C exercise where we are given prototypes, and we have to turn them into functions.
I stumbled onto the following prototype:
void ft_lstdelone(t_list *lst, void (*del)(void*))
This function is supposed to delete a node from a linked list, but I don't understand what is happening in the second argument "void (*del)(void*)".
The description of the exercise has:
Parameters -
#1 The element to free.
#2 The address of the function used to delete the content.
Description - Takes as a parameter an element and frees the
memory of the element’s content using the function
’del’ given as a parameter and free the element.
The memory of ’next’ must not be freed.
I take from this that I have to use a function as an argument, but it doesn't make any sense.
Can someone help me unwrap what this means?

It actually makes a lot of sense. It is a function pointer, that is, ft_lstdelone will find the location of the element. If it was the first element, then the new first element will be its next. If it was the last element, then its previous will point to null. Otherwise its previous will point to its next.
However, how will you remove the actual item? Will you call free? It seems to be a logical approach first, but if you think it through, you will realize that it's a naive approach. If your list contains elements of composite types, then calling free on it will free the address of your data, but the inner members of your data will still hold some allocated data. This raises the possible issue of memory leak, so, depending on the data type you have at your item, you will have to free it in different manners. This is only known at the time when you call ft_lsdelone, because at that point you know the data type of your data.
So, in order to be able to cope with the different scenarios, the function separates the concerns. This function is only concerned in the manner of how an item is to be removed from a list, but will not worry about its deallocation. Instead, it trusts its caller with the deallocation and expects to get a function that is assumed to handle the deallocation properly.

Related

How to prevent buffer overflow

I am being passed an array from a C program that does not include the size of the array; that is, it just passes a pointer to the array. The array is a generic type <Item>. How can I determine the end of the array in order to detect a buffer overflow?
I tried iterating through the array until I received something that wasn't an <Item>. That worked most of the time but sometimes the nonsense at the end Would be of type <Item>. I am using C and calling a function from an external class I had no deal in developing. <Item> is a struct with multiple references to other arrays (sort of like a linked list).
EDIT:
The api stated that the array was intended to be a read-only version. The problem is I cannot read it if I do not know the size. It doesn't appear there is a sentinel value. There is a random comment stating that if the size is needed use sizeOf (array)/sizeOf (Item) which doesn't work. It was developed by a team that no longer works here. The problem is other code already relies on this C code and I cannot change it without fear of ruining other code.
It is not possible to determine the end of an array based on just a pointer to an element of that array.
I tried iterating through the array until I received something that wasn't an <Item>
It's also not possible to determine whether particular memory location contains an object of particular type - or whether it contains any object. Even if you could, how would you determine if the object that you find is really part of the array and not just a separate <Item> object that happens to be there?
A possible solution is to use a sentinel value to represent the end of an array. For example, you could define the interface such that <Item>.member == 0 if and only if that is the last element of the array. This is similar to how null-terminated strings work.
If all you have is a pointer and no size or known "end-of-array" marker (sentinel) in the data, then you have an impossible situation. There is no way in that case to determine the size/end of the passed array.

Changing a pointer as a result of destroying an "object" in C

As part of a course I am attending at the moment, we are working in C with self-developed low level libraries, and we are now working in our final project, which is a game.
At a certain point, it seemed relevant to have a struct (serving as a sort of object) that held some important information about the current game status, namely a pointer to a player "object" (can't really call the simulated objects we are using actual objects, can we?).
It would go something like this:
typedef struct {
//Holds relevant information about game current state
state_st currstate;
//Buffer of events to process ('array of events')
//Needs to be pointers because of deallocating memory
event_st ** event_buffer;
//Indicates the size of the event buffer array above
unsigned int n_events_to_process;
//... Other members ...
//Pointer to a player (Pointer to allow allocation and deallocation)
Player * player;
//Flag that indicates if a player has been created
bool player_created;
} Game_Info;
The problem is the following:
If we are to stick to the design philosophy that is used in most of this course, we are to "abstract" these "objects" using functions like Game_Info * create_game_info() and destroy_game_info(Game_Info * gi_ptr) to act as constructors and destructors for these "objects" (also, "member functions" would be something like update_game_state(Game_Info * gi_ptr), acting like C++ by passing the normally implicit this as the first argument).
Therefore, as a way of detecting if the player object inside a Game_Info "instance" had already been deleted I am comparing the player pointer to NULL, since in all of the "destructors", after deallocating the memory I set the passed pointer to NULL, to show that the object was successfully deallocated.
This obviously causes a problem (which I did not detect at first, and thus the player_created bool flag that fixed it while I still was getting a grasp on what was happening) which is that because the pointer is passed by copy and not by reference, it is not set to NULL after the call to the "object" "destructor", and thus comparing it to NULL is not a reliable way to know if the pointer was deallocated.
I am writing this, then, to ask for input on what would be the best way to overcome this problem:
A flag to indicate if an "object" is "instanced" or not - using the flag instead of ptr == NULL in comparisons to assert if the "object" is "instanced" - the solution I am currently using
Passing a pointer to the pointer (calling the functions with &player instead of only player) - would enable setting to NULL
Setting the pointer to NULL one "level" above, after calling the "destructor"
Any other solution, since I am not very experienced in C and am probably overlooking an easier way to solve this problem.
Thank you for reading and for any advice you might be able to provide!
I am writing this, then, to ask for input on what would be the best way to overcome this problem: …
What would be the best way is primarily opinion-based, but of the ways you listed the worst is the first, where one has to keep two variables (pointer and flag) synchronized.
Any other solution…
Another solution would be using a macro, e. g.:
#define destroy_player(p) do { /* whatever cleanup needed */; free(p), p = NULL; } while (0)
…
destroy_player(gi_ptr->player);

Implementation of Singly-Linked List from Loudon's Algorithm Book

I am reading Mastering Algorithms with C by Kyle Loudon, and currently I am struggling with Loudon's implementation of Singly-Linked List in Chapter 5.
Here are the links to the source code. I apologize for not posting them here as they are a bit long.
list.h
list.c
My question is related to the destroy in list.c as it is mentioned in line 11 under
void list_init(List* list, void (*destroy)(void* data))
as list->destroy = destroy
and then again in line 24 as
list->destroy(data).
All I know is that this destroy is different from the function list_destroy but I have no idea what it is. Is it a function or is it just a pointer? What purpose does it serve in the list_init() function for initializing a linked list?
I really appreciate your time and help! The source code is linked above.
It is a function pointer. When you create an instance of this list, you also have to hand the init_list function a function which it will use to destroy the info.
The purpose of a linked list is to store information, and the linked list structure is there to give some structure to
this data. Hence, each element of the list contains a pointer to some data, and a pointer to the next element in the list. However, you want the list to able to handle multiple kinds of data.
Suppose you want to remove an element of the list, then there are basically two things that have to happen:
The data needs to be destroyed
The linked list structure must be restored. Meaning that the predecessor of the element you removed must point to
the next element in the list.
Since you do not know beforehand what kind of data the data pointer in the list will contain, for step 1 a function pointer is provided to handle the destroying of that data.
A linked list is a data structure made up of nodes, each of which contains or links to one piece of data.
The destroy function destroys just one node out of the list.
The list_destroy function destroys an entire list.
In the given implementation, the node actually contains a pointer to its destroy function, and accesses it by dereferencing that pointer. As it happens (so far), all nodes point to the same destroy function. But with more complex data structures this pattern allows multiple types of nodes to be in the data structure. And the equivalent of the list_destroy function will correctly destroy each node type correctly since the node knows how it should be destroyed.

A no-op device for function pointer tables?

void table_no_op()
{
// this is for function table elements that do nothing,
// fills space between states, use less of them
return;
}
I am currently using this to define a "zero" in a function pointer table, where the input index is supposed to do nothing. Is it okay or something glaringly wrong?
While there's nothing wrong with the no-op per se (in general, this is called Null Object Pattern), I would be worried about the function declaration - i.e. does every function in the table take 0 arguments and return void?
A counterexample would be OpenGL where you often retrieve a pointer to function and cast it to the desired type yourself - but casting a void->void pointer to something else, e.g. (int, int)->int would be undefined behavior and likely cause crash (or uninitialized return value, or else).
So, if the functions in the table are homogeneous - go for it. If not - better do something else.
EDIT: You can only do 2 things with a function pointer - cast it to a different function pointer; and call, but only with the original type.
See http://blog.frama-c.com/index.php?post/2013/08/24/Function-pointers-in-C for details. Raymond Chen has another example here - http://blogs.msdn.com/b/oldnewthing/archive/2011/05/06/10161590.aspx
EDIT2: However, you may make a number of no_ops (noop_IntInt_Int, noop_IntDouble_Double and so on... then if you match the types every time, that might work)

Get struct's size passed as void to function

I'm changing some codes in a database library. The way it works I send a void pointer, to get the size of it I call a query and using the query I calculate the size of the structure. Now the problem is I receive the struct as params but the function fails before/in the middle of the first fetch. After that I need to clear the structure, but I dont even have the size.
I know the best way is send the size of the structure as a param, but I have thousands and thousands programs already compiled, the library is from 1996, so I need to find a way to calculate the structure size even if the type is void.
One idea I had was to calculate the position of the next element that is not in the structure
0x000010 0x000042
[int|char[30]|int|int][int]
So the size is 32, because the 0x00042-0x000010 is 32.
Is there a way to know when I got out of the structure.
the prototype of the function is
int getData(char* fields, void* myStruct)
I need to find out the structure size.
Sorry if I missed some information, the code is HUGE and unfortunately I cannot post it here.
No, in general there's no way, given a void *, to figure out what you're after. The only thing you can do is compare it against NULL, which of course doesn't help here.
Note that there's nothing in the void * that even says it points at a struct, it could just as well be pointing into the middle of an array.
If you have some global means of recording the pointers before they're passed to getData(), you might be able to implement a look-up function that simply compares the pointer value against those previously recorded, but that's just using the pointer value as a key.

Resources