Thomas Sampson


Leave a comment

Working in C!

This last week I have been treated to working on a code base written entirely in C code, no C++, all C!

While this has been an interesting challenge there are definitely times when I really missed some of the features provided in C++ and realised how much the standard template library is taken for granted! Anyway, as usual I only really post things on here which are of use to myself as reference at a later date, or items I found it particularly hard to track down elsewhere on the web. This post falls into both categories, and being such a fundamental issue I’m surprised that it took so long to find a solution.

I was working on adding a small lightweight XML library to the existing C code base. I was continuously faced with the problem of requiring some form of expandable buffer, in most cases to hold c strings (null terminated character arrays). The root of the problem is that there is no string type in C, no vectors and no dynamic arrays of any kind. This means that whenever you want to use one of the string functions such as strcopy,  strcat or sprintf, you are always required to know the size of the buffer upfront and allocate memory appropriately (freeing the memory when the buffer is disposed).

The main function I was concerned with was sprintf which I required in order to build up strings for the xml documents. The length of the strings produced by sprintf could be very varied and picking a fixed buffer size would in most cases be over the top, and in some cases dangerous as buffer overflows could potentially always occur, corrupting the heap. Luckily I discovered the following technique which allows you to first print the formatted string to a dummy file (no data is actually written to a file and no I/O occurs) using fprintf. Once the fprintf call has completed (assuming the format string / parameters were valid) you can then check the return value to find out exactly how many characters were written to the dummy buffer, providing you with the exact buffer size required for allocation!

Once a buffer of the correct size is allocated sprintf can then be used with the same paramaters to safely fill in the buffer. This method does have its drawbacks. I guess that there is extra overhead incurred in formatting the string twice and gaining a handle to the dummy file. However, as far as I can find this is the only way to do this properly without using fixed size buffers. One work of warning, this technique should work across platforms but “:NULL” should be replaced with “nul” on unix systems. A simple #ifdef UNIX should sort that out!

FILE* f = fopen(":NULL","w");

char* buffer = 0;

int n = fprintf(f,"hello %s", "world");

buffer = (char*)malloc(n);

sprintf(buffer, "hello %s", "world");

//use buffer

free(buffer);
Advertisements


Leave a comment

“Smart Pointers”

Smart pointers are objects used to manage resources which were created on the heap, and allow such resources to be deleted automatically whenever their parent smart pointer would normally go out of scope. This avoids the common problem of calling new to allocate some space on the stack for an object (returning a pointer to the object), using that pointer, and then never calling delete (causing a memory leak to occur).

Another benefit of using smart pointers is the ability to have references to heap resources counted (using reference counting). This is useful when you have a particular resource on the heap, let’s call this object x. There are n number of objects around your program which all carry a pointer to object x to use its data and functions. In this case when should object x be destroyed and the memory freed? The answer to this is typically “When n =0”. So, when the last object containing a reference to object x is removed, the reference count of object x reaches 0 and the smart pointer can then de-allocate any memory consumed by object x on the heap.

Implementation
Smart pointers have two key components. Firstly they have a pointer onto the resource being managed (in the example below this is m_data). Secondly they have a pointer to a reference counting object which allows them to keep a track of how many references there are to the managed resource, in this case rc). The reason a pointer to the reference counter is used rather than a pure data member, is that all references to the managed resource (that is, all copies of an instance of a smart pointer) need to share the same reference count as there can only be one reference count per managed object.

The example below shows a quick smart pointer implementation I wrote. There are much better tested implementations found in the stl and boost libraries but my example below just demonstrates simply what is going off.

The smart pointer object is a template class, allowing it to manage a pointer to any type of resource (but not arrays!). When the smart pointer is constructed it is given a pointer to the heap allocated object and it also creates a unique reference count for this object (From this point on, all copies of the smart pointer for the managed object share a pointer to the reference count so they can all communicate). After the first initialisation, whenever a “copy” of the resource is needed by other methods or objects (I say copy because it is only a copy of the reference they require, not a physical copy of the object) the copy constructor of the smart pointer object is called, incrementing the reference count. Whenever the smart pointer object gets destructed, the reference count for the underlying object is decremented. This way the destructor of the smart pointer can always check to see if no more references remain, and free the resources.


#include <iostream>
#include <vector>

class ref_count
{
    public:
        unsigned int count;
        ref_count() : count( 1) {}
};

template<class T>
class smart_ptr
{
    public:
        T* m_data;
        ref_count* rc;

        smart_ptr(T* data) : m_data( data), rc( new ref_count())
        {
            std::cout << "Smart pointer constructed for object "<<m_data<< "\n";
        }
        smart_ptr(const smart_ptr& source)
        {
            m_data=source.m_data;
            rc=source.rc;
            ++rc->count;
            std::cout << "Reference added for object " << m_data << "\n Ref Count = "<<rc->count<<"\n";
        }
        ~smart_ptr()
        {
            if( rc->count==1) //if last one
            {
                std::cout << "Smart pointer destructed for object "<<m_data<< "\n OBJECT RELEASED AT "<<m_data<<"\n";
                delete m_data;
            }
            else
            {
                --rc->count;
                std::cout << "Reference removed for object " << m_data << "\n Ref Count = "<<rc->count<<"\n";
            }
        }
};

class Car
{
    public:
        Car() { std::cout << "car constructed at " << this << "\n"; }
        ~Car() { std::cout << "car destructed at " << this << "\n"; }
};

void foo()
{
    std::vector<smart_ptr<Car>> garage1, garage2;
    smart_ptr<Car> car_ptr( new Car());
    garage1.push_back(car_ptr);
    garage2.push_back(car_ptr);
}

int main(int argc, char* argv[])
{
    foo();
    std::cin.get();
    return 0;
}


3 Comments

Dynamic Arrays in C++

Update: After looking back at this post I realised that the title “Dynamic Arrays in C++” is pretty misleading, I think this was basically way back when I figured out how do do memory allocation! For anyone looking to do real dynamic arrays / collections, consider the std::vector class or use a linked list.


C++I have only started using C++ properly over the past few months and I’m realising that many of the features and aspects I took for granted in interpreted languages, are implemented in a much more complicated way in c++!

For example if you wanted to create a dynamic array in c# (as below) the .NET framework will do all the memory allocation and management for you and let you initialise an array of your chosen size at run time (when the size of the array cannot be determined at compile time)

int[] temp = new int[varName] //Where varName could be an integer given by the user


Another interesting point at this stage is that after c# initialises the array dynamicaly, for example with a dimension of 3. When you try and access temp[20] for example, the .net framework instantly detects you are breaching the size of the array and throws an “Out of bounds” exception. However in c++ (and this applies to static and dynamic arrays) accesing a position outside the array simply looks up in memory PAST the array and starts reading random data, not even necessarily from your application!

Anyway, to make a dynamic array in c++ we must follow 3 steps

  1. use the new keyword to initialise the array in memory
  2. ensure that the memory allocation for the array was successfull, catching the failure of this event
  3. delete the array from memory after use (as c++ will not dispose of it automatically)

The example below simply gets a number from the user and then initialises an array with the dimension the user has specified.


int mySize( 0);
cin >> mySize;
int* myArray = new int[mySize];
if(myArray!=0)
{
  //catch failure of array initialisation
}
else
{
  //Work with array....
  delete[] myArray;
}