libabigail
Memory management

How objects' lifetime is handled in libabigail. More...

How objects' lifetime is handled in libabigail.

For memory management and garbage collection of libabigail's IR artifacts, we use std::shared_ptr and std::weak_ptr.

When manipulating these IR artifacts, there are a few rules to keep in mind.

The declaration for a type is owned by only one scope

This means that for each instance of abigail::type_base (a type) there is an instance of abigail::scope_decl that owns a abigail::decl_base_sptr (a shared pointer to an abigail::decl_base) that points to the declaration of that type. The abigail::type_base_sptr is added to the scope using the function abigail::add_decl_to_scope().

There is a kind of type that is usually not syntactically owned by a scope: it's function type. In libabigail, function types are represented by abigail::function_type and abigail::method_type. These types must be owned by the translation unit they originate from. Adding them to the translation unit must be done by a call to the method function abigail::translation::bind_function_type_life_time().

A declaration that has a type does NOT own the type

This means that, for instance, in an abigail::var_decl (a variable declaration), the type of the declaration is not owned by the declaration. In other (concrete) words, the variable declaration doesn't have a shared pointer to the type. Rather, it has a *weak* pointer to its type. That means that it has a data member of type abigail::type_base_wptr that contains the type of the declaration.

But then abigail::var_decl::get_type() returns a shared pointer that is constructed from the internal weak pointer to the type. That way, users of the type of the var can own a temporary reference on it and be assured that the type's life time is long enough for their need.

Likewise, data members, function and template parameters similarly have weak pointers on their type.

If, for a reason, you really need to keep a type alive for the entire lifetime of the type system, then you can bind the life time of that type to the life time of the environment that is supposed to outlive the type system. You do that by passing the type to the function environment::keep_type_alive().