The main issue with manual allocation of memory is that if you allocate memory in one place, you need to remember to eventually deallocate it as soon as you do not need it, in order to free space. Keeping track of the lifetime of an object is not easy, and it can be easy to lose track once you reach a certain size of codebase. It therefore can be easier to automate the process of allocating and deallocating memory for a specific object in memory. One such way is reference counting.

It will initialize the reference count to 1, as usually the caller of malloc will have a reference. Any procedure that stores a reference increments the count. Any procedure that discards a reference decrements the count. This means that free will never be called directly, and the object is automatically freed when the counter goes to zero.

Uses

Reference counting is most commonly used for automating garbage collection. The main advantage reference counting offers over the other most used method for garbage collection, tracing, is that objects are reclaimed as soon as they can no longer be referenced, and in incremental fashion, without long pauses for collection cycles and with clearly defined lifetimes for every object. So in real-time applications or systems with limited memory, this method can offer significant advantages. It is also relatively easy to implement.

Related to this use, variations of so called smart pointers in C++ use reference counting as mechanisms to improve memory management in large-scale projects and reduce memory-related bugs.

Implementation

An example implementation could look something like the following:

struct buffer *rc_malloc(){ 
	struct buffer *buf = malloc(sizeof(struct buffer));
	buf->ref_count = 1;
	return buf;
}
 
void rc_keep_ref(struct buffer *buf){
	buf->ref_count++;
}
 
void rc_free_ref(struct buffer *buf) {
	buf->ref_count--;
	if (buf->ref_count == 0)
		free(buf);
}

As an overview, this implementation has three methods where when you want to allocate on the heap, instead of allocating your object directly, you allocate a buffer (which would effectively contain two things, the object itself and a numeric value ref_count), and then return a pointer to that buffer.

This buffer is then set to 1, since there’s already one pointer towards an object. Then, at every place you reference that object, you would manually call rc_keep_ref to increment the amount of things pointing towards that object. Then, whenever a pointer towards that object is no longer needed, you call rc_free_ref, only actually free()ing the object if there are 0 references remaining.

Benefits

This functionally makes common memory management errors like dangling pointers and double free significantly harder to accidentally do, though they are still possible.