Pointer to smart pointer, purpose - shared-ptr

Can anyone explain how does this work.
shared_ptr<T> *p = new shared_ptr<T>(x);
Should I do delete p; p = NULL;
Thank you

shared_ptr<T> *p = new shared_ptr<T>(x);
This is extremely non-idiomatic, not recommended, not good design.
shared_ptr<T> is for automatic memory management: you don't have to delete the object managed by shared_ptr. You need to make sure that
x points to a T object allocated with new
no other code tries to deallocate x
For some reason the code allocates a shared_ptr with new: the automatic memory management tool (shared_ptr) is managed manually here: you must remember to delete the shared_ptr when you don't need it (and not earlier), "it" being the tool whose sole purpose is to do avoid the risk of forgetting to do a delete or doing it too early.
Should I do delete p; p = NULL;
Yes you need delete p; and p = NULL; is optional but necessary if other code might need to check whether p points to an object.
An analogy would be to have an alarm clock to wake you up, setup the alarm at time T, remove the battery in the clock, then ask a friend to put the battery back in the alarm clock at time T so it can wake you up.
At any rate, you should question the quality of the tools that produce such code.

Related

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

How to completely free a timer(timer_list)?

I am working on an application with multiple timers. When the application starts, everything is just runs as standard, except I have some pointers point to the timer.
I will show a piece of sample code to clarify my purpose:
---------------------------init foo---------------------
init_timer(&timer1);//timer1 definition is outside the function, as struct timer_list timer1
timer1.expires = jiffies+SECONDS_TO_JIFFIES(5);
timer1.data = (unsigned long) data;
timer1.function = callback_foo;
timer1_pointer = &timer1;//timer1_pointer definition is outside the function, as struct timer_list *timer1_pointer
------------------the other function after init---------------
add_timer(timer1_pointer);
-------------------deinit---------------------------
del_timer_sync(&timer1);
It works fine in the beginning, however it will always crash at add_timer when the whole flow (deinit->init->the other function->...) runs again.
It makes me feel something is wrong in the deinit. Since delete timer only detach instead of delete. Rerun the flow may mesh up the timer list.
So are there any ways to safely free it? Or if you find any other mistakes I made?
OK,since no one answered, I just post some thoughts and I finally proved it truly the reason that trigger the crash.
It seems that, if the timer are required to be relaunched and deleted sometimes during a long run application, it is necessary to free/clean the timer_list. This del_timer_sync/del_timer not really delete it as I thought. Since the project I am working on is complicated, I guess some dude just make things messy and affect me..I will try to dig it later if I have time.

Could someone help me clear some confusions about pointers? in C

What i understand right now is.
int a = 100;
int *a_ptr; // creates pointer variable named a_ptr and points to type int
a_ptr = &a; // a_ptr is address of a
*a_ptr = 5; // value of pointer = value of a now set to 5.
What i dont understand is the point of pointers is to occupy the address of another variable as its right value or content isnt it?
if *a_ptr is the value shouldn't it be *a_ptr = &a;?
Thanks
Think of a pointer as a road sign: It tells you where you can find something. Nothing more, nothing less. The value/reason for pointers to exist is because it's a concept that we're actually all too familiar with. C passes everything by value. Let's use a far-fetched analogy that, I believe, will clear a couple of things up for you:
Imagine having been on holiday and telling someone about the hotel you stayed in. Instead of describing it in great detail, you'd give the other person the name, the address, and perhaps some more details that could help someone to find the place. You would not set about describing the entire thing in detail, nor would you tear the hotel down and take it with you, let alone rebuild it every time you tell somebody about it.
Back to C: C passes everything by value. In this analogy, that would be like handing everyone a 1-to-1 scale replica of the hotel you're raving on about. That's expensive, time consuming and really quite annoying. The people you've given a copy of the hotel to can change it, but you'd never know: there's a common starting point (the original hotel), but every copy is independent of one another after that.
Like in real life, you'd simply write the address of the hotel down and give that out to family and friends. That's what C does with pointers: it tells you where you can find something (a struct hotel or int), and others can use that address to travel to it.
The added benefit being that if some of your friends actually pay a visit to that place, they can tell you that it's changed in certain ways: the colour is now green, not blue, the owners have changed, etc...
Using the address allows everyone who has the address to have access to up-to-date information about the place.
If the hotel closes down, the address become pointless, but of course, if someone uses the address you gave them thinking they're going to stay in a great place, they'll get angry. What happens next is hard to predict (Undefined behaviour).
So in resuming:
int x = 123;// a hotel
int *x_address = &x;//an address to the hotel
int *for_friend = &x;
int *friend2 = &x; // you can hand out sever addresses to the same hotel
*x_address += 1; // read this as *(travel to)x_address to arrive at hotel X, and stay += 1 night or something
//friend2 wants to see how many nights were spent in hotel x:
printf("%d\n", *friend2);//124 -> 123 originaly + *x_address += 1
If x goes out of scope, that's the equivalent of the hotel closing. If sombody *x_address (travels to x), then their behaviour is undefined.
I've used different analogies in the past to explain in what way you can look at pointers to make them easier to understand, I've written this a while back, don't know if this makes things any clearer, but I thought I'd just post the link here:
Pointers are easy
if *a_ptr is the value shouldn't it be *a_ptr = &a;?
*a_ptr is the value, but &a is not the value, that is a pointer to the value, so they have different types.
So, the value can be set through the pointer, *a_ptr = a, or the pointer can be set to point at a value, a_ptr = &a.

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!

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

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.

Resources