C99: Return a value after it's been free'd from the heap - c

I'm wondering if there's a way to return a value just before it's free'd from the heap.
My problem is that if I do something like this:
queue_item *dequeue(queue *this) {
node old = this->front;
this->front = old->link;
free(old->item);
free(old);
return(old->item);
}
Clearly old->item is taken off the heap before it can be returned. Currently to get around this problem, I store the item that was previously used in a field. Then I free that item the next time I dequeue. Finally, I kill the last item in the queue's destructor.
queue_item prev_item;
queue_item *dequeue(queue *this) {
assert (!queue_isempty (this));
node old = this->front;
this->front = old->link;
queue_item item = old->item;
free(prev_item);
prev_item = old->item;
free(old);
return(old->item);
}
void queue_destruct(queue this) {
free(prev_item);
free(this)
}
But I'm not too happy with this method because I always have an extra item on the heap. Is there a way around this? Is there some sort of elegant solution that I'm missing?

You should never free it while it's still needed. You should never leave it on the heap once it's not.
What you can do is abstract away the details of how to create it and how to destroy it. But you can't cheat time. You need something that knows when to create and when to destroy it. You need something that knows how to create and how to destroy it. Those two things don't have to be the same thing. One can call the other. But don't request creation with out thinking about when to destroy.
Keep in mind that moving big things around in memory is expensive and often pointless. Keep in mind that you don't dictate where something is allocated, you get told. Once something has been allocated you can share that address. But as the thing, the level, that requested allocation of it, it's YOUR JOB clean up after yourself.
This is something you simply can't do with just one function. You'd need two. One for each moment in time.
If you're at a level where something else asked you to create it you can make it that things job to tell you when to destroy it. It's IN BETWEEN those two moments in time that you can hand up the address and let something above you use it. That something is now responsible for asking you to clean up.
This is what people mean when they say that malloc and free need to be used in pairs. The same can be said of any resource you allocate.

Related

Deleting from a BST in C

I am very new to C programming and am using it for one of my classes. The project I am working on involves a BST and deleting nodes from it.
In terms of memory and allocation, if all the nodes in the tree are created using malloc() function, is it enough to call free on a particular node to delete it? Or do I have to set the pointer from the parent to NULL as well?
A pointer which points to nothing will by default have a value of NULL, so I don't see why you'd need to manually set it. It wouldn't hurt anything, but freeing the memory would be sufficient.
You can always write a quick test to make sure that the value of the now non-existent child is in fact NULL... something like this (not tested, just a general idea):
int checkNull(Node* x){
return(x->child == NULL ? 1 : 0);
}
If checkNull() returns 1, you're good. If not, maybe you do have to manually reset it after all. Hope this helps.

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);

Design of API's for data structures and algorithms

I recently implemented binary search tree, linked lists etc as a learning exercise. II implemented several API's like Insert,delete etc.
For example the Insert node API looks like
void insertNode(Node** root, Node* node)
The application would allocate memory for the node to be inserted. i.e node and assign the value/key and pass to this function.
1) My question is whether this is right approach in general? Or does the application only need to pass the value/key to insertNode function and the this function allocates memory?
i.e void insertNode(Node** root, int key)
{
malloc for node here
}
2) What is a good design practice- the application handles allocating memory and free or this library of APi's ?
Thanks
General principles:
Whoever allocates memory should also have responsibility to delete it.
Make the client's job as easy as possible
Think about thread safety
So, don't have client allocate the memory being managed by the tree. However we then need to think carefully about what a find or search should return.
You might look at example code to see what policies other folk have taken for collection APIs. For example.
In passing you don't need the double pointer for your root.
If someone has root pointing to an object { left -> ..., right -> ...} then if you pass root as Node* your code can write
root->left = newValue;
you're modifying what root points to not root itself. By passing the double pointer you're allowing the structure to be completely relocated because someone can write:
*root = completelyNewTree
which I doubt you intend.
Now for inserting I'd suggest passing in the new value, but have the collection allocate space and copy it. The collection now has complete control over the data it holds, and anything it returns should be copied. We don't want clients messing with the tree directly (thread safety).
This implies that for result of a find either the caller must pre-allocate a buffer or we must clearly document that the collection is returning an allocated copy that the caller must delete.
And yes, working in any Garbage Collecting language is much easier!

Too many frees when freeing graph

I have created a graph datastructure using linked lists. With this code:
typedef struct vertexNode *vertexPointer;
typedef struct edgeNode *edgePointer;
void freeGraph(vertexPointer); /* announce function */
struct edgeNode{
vertexPointer connectsTo;
edgePointer next;
};
struct vertexNode{
int vertex;
edgePointer next;
};
Then I create a graph in which I have 4 nodes, lets say A, B, C and D, where:
A connects to D via B and A connects to D via C. With linked lists I imagine it looks like this:
Finally, I try to free the graph with freeGraph(graph).
void freeEdge(edgePointer e){
if (e != NULL) {
freeEdge(e->next);
freeGraph(e->connectsTo);
free(e);
e = NULL;
}
}
void freeGraph(vertexPointer v){
if (v != NULL) {
freeEdge(v->next);
free(v);
v = NULL;
}
}
That's where valgrind starts complaining with "Invalid read of size 4", "Address 0x41fb0d4 is 4 bytes inside a block of size 8 free'd" and "Invalid free()". Also it says it did 8 mallocs and 9 frees.
I think the problem is that the memory for node D is already freed and then I'm trying to free it again. But I don't see any way to do this right without having to alter the datastructure.
What is the best way to prevent these errors and free the graph correctly, if possible without having to alter the datastructure? Also if there are any other problems with this code, please tell. Thanks!
greets,
semicolon
The lack of knowing all the references makes this a bit difficult. A bit of a hack, but faced with the same issue I would likely use a pointer set (a list of unique values, in this case pointers).
Walk the entire graph, pushing nodes pointers into the set only if
not already present (this the definition of 'set')
Walk the set, freeing each pointer (since they're unique, no issue of
a double-free)
Set graph to NULL.
I'm sure there is an elegant recursive solution to this, but faced with the task as stated, this seems doable and not overtly complicated.
Instead of allocating the nodes and edges on a global heap, maybe you can allocate them in a memory pool. To free the graph, free the whole pool.
I would approach this problem by designing a way to first cleanly remove each node from the graph before freeing it. To do this cleanly you will have to figure out what other nodes are referencing the node you are about to delete and remove those edges. Once the edges are removed, if you happen to come around to another node that had previously referenced the deleted node, the edge will already be gone and you won't be able to try to delete it again.
The easiest way would be to modify your data structure to hold a reference to "incoming" edges. That way you could do something like:
v->incoming[i]->next = null; // do this for each edge in incoming
freeEdge(v->next);
free(v);
v = NULL;
If you didn't want to update the data structure you are left with a hard problem of searching your graph for nodes that have edges to the node you want to delete.
It's because you've got two recursions going on here, and they're stepping on each other. freeGraph is called once to free D (say, from B) and then when the initial call to freeGraph comes back from freeEdge, you try freeing v -- which was already taken care of deeper down. That's a poor explanation without an illustration, but there ya go.
You can get rid of one recursions so they're not "crossing over", or you can check before each free to see if that node has already been taken care of by the other branch of the recursion.
Yes, the problem is that D can be reached over two paths and freed twice.
You can do it in 2 phases:
Phase 1: Insert the nodes you reached into a "set" datastructure.
Phase 2: free the nodes in the "set" datastructure.
A possible implementation of that set datastructure, which requires extending your datastructure:
Mark all nodes in the datastructure with a boolean flag, so you don't insert them twice.
Use another "next"-pointer for a second linked list of all the nodes. A simple one.
Another implementation, without extending your datastructure: SOmething like C++ std::set<>
Another problem: Are you sure that all nodes can be reached, when you start from A?
To avoid this problem, insert all nodes into the "set" datastructure at creation time (you won't need the marking, then).

How to avoid multiple deallocation

A Scene struct has a pointer to (a linked list of) SceneObjects.
Each SceneObject refers to a Mesh.
Some SceneObjects may however refer to the same Mesh (by sharing the same pointer - or handle, see later - to the Mesh). Meshes are pretty big and doing it this way has obvious advantages for rendering speed.
typedef struct {
Mesh *mesh;
...
struct SceneObject *next;
} SceneObject;
typedef struct Scene {
SceneObject *objects;
...
} Scene;
My question:
How do I free a Scene, while avoiding to free the same Mesh pointer multiple times?
I thought I could solve this by using handle to Mesh (Mesh** mesh_handle) instead of a pointer so I could set the referenced Mesh pointer to 0, and let successive frees on it just free 0, but I can't make it work. I just can't get my head around how to avoid multiple deallocations.
Am I forced to keep references for such a scenario? Or am I forced to put all the Mesh objects into a separate Mesh table and free it separately? Is there a way to tackle this without doing these things? By tagging the objects as instances of each other I can naturally adjust the free algorithm so it deals with the problem, but I was wondering if there is a more 'pure' solution for this problem.
One standard solution is to have reference counters, that is every object that can possibly be referred by many other objects must have a counter that remembers how many of them are pointing it. This is done with something like
typedef struct T_Object
{
int refcount;
....
} Object;
Object *newObject(....)
{
Object *obj = my_malloc(sizeof(Object));
obj->refcount = 1;
....
return obj;
}
Object *ref(Object *p)
{
if (p) p->refcount++;
return p;
}
void deref(Object *p)
{
if (p && p->refcount-- == 1)
destroyObject(p);
}
Who first allocates the object will be the first owner (hence the counter is initialized to 1). When you need to store the pointer in other places every time you should store ref(p) instad, to be sure to increment the counter. When someone is not going to point to it anymore you should call deref(p). Once the last reference to the object is gone the counter will become zero and the deref call will actually destroy the object.
It takes some discipline to get it working (you should always think when calling ref and deref) but it's possible to write complex software that has zero leaks using this approach.
A simpler solution that is sometimes applicable is having all your shared objects also stored in a separate list... you freely assign and change complex data structures pointing to these objects but you never free them during the normal use. Only when you need to throw everything away you deallocate those objects by using that separate list.
Note that this approach is possible only if you're not allocating many objects during the "normal use" because in that case delaying the destruction could be not viable.

Resources