The function gtk_tree_store_clear() does what the documentation says it does: the store is cleared and all lines inside the associated tree view disappear.
Does this function also free the memory that the store used? For example, if the store had 1,000 lines of gchar *, is all that memory freed?
Yes, otherwise everyone using GtkTreeStore (or GtkListStore for that matter) that would be dealing with a major memory leak. :-)
That's also the reason why you have to pass a list of GTypes to the constructors of those classes: GTK uses them to lookup on how to free them. If you want to know the implementation details: both classes internally use an internal class called GtkTreeDataList which implements this.
The fact that it also knows about thise GTypes is also the reason why you don't need to explicitly strdup() your strings when passing them one for example: that's also something the subclass will lookup from the respective column types.
Related
I have two arrays:
struct Data {
all_objects: Vec<Rc<dyn Drawable>>;
selected_objects: Vec<Rc<dyn Drawable>>;
}
selected_objects is guarenteed to be a subset of all_objects. I want to be able to somehow be able to add or remove mutable references to selected objects.
I can add the objects easily enough to selected_objects:
Rc::get_mut(selected_object).unwrap().select(true);
self.selected_objects.push(selected_object.clone());
However, if I later try:
for obj in self.selected_objects.iter_mut() {
Rc::get_mut(obj).unwrap().select(false);
}
This gives a runtime error, which matches the documentation for get_mut: "Returns None otherwise, because it is not safe to mutate a shared value."
However, I really want to be able to access and call arbitrary methods on both arrays, so I can efficiently perform operations on the selection, while also being able to still perform operations for all objects.
It seems Rc does not support this, it seems RefMut is missing a Clone() that alows me to put it into multiple arrays, plus not actually supporting dyn types. Box is also missing a Clone(). So my question is, how do you store writable pointers in multiple arrays? Is there another type of smart pointer for this purpose? Do I need to nest them? Is there some other data structure more suitable? Is there a way to give up the writable reference?
Ok, it took me a bit of trial and error, but I have a ugly solution:
struct Data {
all_objects: Vec<Rc<RefCell<dyn Drawable>>>;
selected_objects: Vec<Rc<RefCell<dyn Drawable>>>;
}
The Rc allows you to store multiple references to an object. RefCell makes these references mutable. Now the only thing I have to do is call .borrow() every time I use a object.
While this seems to work and be reasonably versitle, I'm still open for cleaner solutions.
I've been writing code, and I'm in a point where I should have another program calling my library. I should make a reference counter for the output of my library. Basic idea as I have understood is that, I need to have reference counter struct inside my struct that I want to pass around. So my questions are following:
What should I keep in mind when making a reference counter?
What are complete don'ts when making a reference counter?
Is there really detailed examples where to start with this?
Thank you for your answers in advance!
Reference counting allows clients of your library to keep reference objects created by your library on the heap and allows you to keep track of how many references are still active. When the reference count goes to zero you can safely free the memory used by the object. It is a way to implement basic "garbage collection".
In C++, you can do this more easily, by using "smart pointers" that manage the reference count through the constructor and destructor, but it sounds like you are looking to do it in C.
You need to be very clear on the protocol that you expect users of your libraries to follow when accessing your objects so that they properly communicate when a new reference is created or when a reference is no longer needed. Getting this wrong will either prematurely free memory that is still being referenced or cause memory to never be freed (memory leak).
Basically, You include a reference count in your struct, that gets incremented each time that your library returns the struct.
You also need to provide a function that releases the reference:
struct Object {
int ref;
....
}
Object* getObject (...) {
Object *p = .... // find or malloc the object
p->ref++;
return p;
}
void releaseReference (Object* p) {
p->ref--;
if (p->ref == 0) free(p);
}
void grabReference (Object* p) {
p->ref++;
}
Use grabReference() if a client of your library passes a reference to another client (in the above example, the initial caller of your library doesn't need to call grabReference())
If your code is multi-threaded then you need to make sure that you handle this correctly when incrementing or decrementing references
Say I wanted to store objects statically inside their own class. Like this:
public class Foo
{
private static int instance_id = 0;
public static List<Foo> instances = new List<Foo>();
public Foo()
{
instances[instance_id++] = this;
}
}
Why?
I don't need to create unique array structures outside the class (one will do).
I want to map each object to a unique id according to their time of birth.
I will only have one thread with the class in use. Foo will only exist as one set in the program.
I did searching, but could find no mention of this data structure. Is this bad practice? If so, why? Thank you.
{please note, this question is not specific to any language}
There are a couple of potential problems I can see with this setup.
First, since you only have a single array of objects, if you need to update the code so that you have lots of different groups of objects in different contexts, you'll need to do a significant rewrite so that each object ends up getting associated with a different context. Depending on your setup this may not be a problem, but I suspect that in the long term this decision may come back to haunt you.
Second, this approach assumes that you never need to dispose of any objects. Imagine that you want to update your code so that you do a number of different simulations and aggregate the results. If you do this, then you'll end up having your giant array storing pointers to objects you're not using. This means that you'll (1) have a memory leak and (2) have to update all your looping code to skip over objects you no longer care about.
Third, this approach makes it the responsibility of the class, rather than the client, to keep track of all the instances. In some sense, if the purpose of what you're doing is to make it easier for clients to have access to a global list of all the objects that exist, you may want to consider just putting a different list somewhere else that's globally accessible so that the objects themselves aren't the ones responsible for keeping track of themselves.
I would recommend using one of a number of alternate approaches:
Just have the client do this. If the client needs to keep track of all the instances, just have them always create the array they need and populate it. That way, if multiple clients need different arrays, they can do so. You also avoid the memory leak issues if you do this properly.
Have each object take, as part of its constructor, a context in which to be constructed. For example, if all of these objects are nodes in a quadtree, have them take a pointer to the quadtree in which they'll live as a constructor parameter, then have the quadtree object store the list of the nodes in it. After all, it seems like it's really the quadtree's responsibility to keep track of everything.
Keep doing what you're doing, but using something with weak references. For example, you might consider using some variation on a WeakHashMap so that you do store everything, but if the objects are no longer needed, you at least don't have a memory leak.
I was reading an article about array vs list, and the author says that an array is worse than a list, because (among other things) an array is a list of variables, but to me a list is also a list of variables. I mean, I can still do list[3] = new Item().
Actually, I have always somehow saw a List<T> like a wrapper for an array that allows me to use it easily without caring about handling its structure.
What are the internal differences between a T[] and a List<T> in terms of heap/stack memory usage?
Since an array is a static structure, after the initialization, it allocates the memory that you've demanded.
int arr[5];
For example here there are 5 int objects created in memory. But when you use lists, according to its implementation, it gives you first an array with predefined capacity. And while you are adding your elements, if you exceed the capacity then it scales up. In some implementations it just doubles its size, or in some implementations it enlarges itself when the granted capacity is half full.
The author's point about a "list of variables" wasn't about memory. It's that an array contains your internal variables, and returning it allows them to be reassigned by the caller. It comes down to this:
Only pass out an array if it is wrapped up by a read-only object.
If you pass out an internal List<T>, you have the same problem, but here's the key:
We have an extensibility model for lists because lists are classes. We
have no ability to make an “immutable array”. Arrays are what they are
and they’re never going to change.
And, at the time the article was written, the IReadOnlyList interface didn't exist yet (.NET 4.5), though he probably would have mentioned it if it had. I believe he was advocating implementing an IList<T> that would simply throw an exception if you tried to use the setter. Of course, if the user doesn't need the ability to access elements by index, you don't need a list interface at all -- you can just wrap it in a ReadOnlyCollection<T> and return it as an IEnumerable<T>.
Quoting a code snippet :
/**
* list_add - add a new entry
* #new: new entry to be added
* #head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
I have seen similar code in several different programs, especially those manipulating data structures. What is the usual intention in adding this extra level of indirection - why can't the code inside __list_add be put inside list_add ?
If you copy code, it will make maintenance harder. In this example, the extra level of indirection hides the parameter next. It will provide a function with just 2 parameters rather than 3.
If the code inside the __list_add() is copied, it needs to be copied to multiple places. If then the list mechanism is changed somewhat, all of these places need to be updated too, or bugs will start to pop-up (i.e. a FIFO and LIFO implementation of a list show different behavior).
There is always a tradeoff; another level of indirection also adds complexity and possibly overhead, as opposed to duplicating lines of code or having lots of parameters in the API.
It's about code reuse, and avoiding duplication.
__list_add() contains code that is useful in more situations than just this one, and can be shared between several different functions.
Sharing code like this has several advantages:
If there's a bug in __list_add() and you fix it, all the functions that use it get the fix.
If __list_add() gets an enhancement (eg. you make it faster) all the functions get faster.
There's only one place to look when you want to see how items are added to lists.
It can.
However, there are probably other public entries that can share the code in __list_add(). eg, there may be a push() or an insert_head() or something like that.
NOTE: If this is C++ then you might want to rethink calling your variables new, as this is a reserved word.
__list_add will be intended as a "private" internal function which might have multiple uses internally. The public facing list_add is there as a convenient wrapper around it.
This wrapper is inline. If you added the body of __List_add, that too would be inlined. The apaprent goal is to just inline the pushing of the extra head->next argument and nothing else.
That function comes from the linux kernel.
It belongs to the generic list implementation:
Take a look: __list_add()
__list_add() is used in many places: e.g. list_add() which adds an element at a list head, list_add_tail() which adds an element at list tail... It can also be used to insert an element at a given position.
It is also common to define an wrapper function for recursive functions so the initial parameters are set correctly.
See binary search on wikipedia for Recursion (computer science)
Could also be to keep binary compatibility. you have an indirection that allows to keep the ABI invariant.
From http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
When a new version of a library is
binary-incompatible with the old one
the soname needs to change. In C,
there are four basic reasons that a
library would cease to be binary
compatible:
The behavior of a function changes so that it no longer meets its
original specification,
Exported data items change (exception: adding optional items to
the ends of structures is okay, as
long as those structures are only
allocated within the library).
An exported function is removed.
The interface of an exported function changes.