What the name of the memory allocator is, under C++.

Usually, when one is programming in C, the name of the memory allocator is ‘malloc()‘. When programming in C++, this function has been replaced with the ‘new‘ operator, which the reader may not realize, he or she has been using the whole time. The way this works is that, if an object is to be placed on the heap, ‘new‘ allocates a region of memory, and then calls one of the class’s constructors, to fill that region of memory with the object. If the C++ has been properly written, but contains no ‘new‘ operator for an object, then the compiler allocates space for it, usually on the stack, but the constructor call does the same thing. This is also why, technically, the constructor does not return anything. If ‘new‘ was used, then ‘new‘ will return a pointer to this memory location, after the constructor call succeeded.

I suppose a question which could be asked, and which would be slightly more useful, would be, whether it’s legal to use both allocators in the same program. And this question comes back to, whether it’s legal to put pieces of C into a C++ program. And the answer is, ‘Sometimes, Yes.’ I think the biggest problem that some programmers might encounter when doing so, is, failing to keep track of which data-structures are ‘C’ data structures, and which are ‘C++’ objects, in the way the code was written. At that point, C++ does not contain any inherent mechanism to make this distinction obvious. Another problem which some programmers might encounter is, that certain header files will not be compatible with each other, if included in the same program.

Thus, a type of problem to look out for could be, creating C++ ‘string‘ objects, and C arrays prototyped with ‘char *‘ or ‘char[]‘, the latter of which are also referred to as ‘c_strings’, in the same program. A C function that expects a ‘c_string’, will certainly cause a compile error, if it was suddenly fed a C++ ‘string’ object. And this can be even harder to recognize, because C++ ‘string’ objects may be initialized with ‘c_string’ instances, in their constructor calls (just to keep the appearance of the code manageable).

Also, certain environments provide special macros for such string literals, such as, ‘L"Some Text"‘. It’s important not to confuse this one with a standard, legacy c_string. A standard, legacy c_string consists of an array of 8-bit characters (‘char‘), while this prefix creates of an array of ‘wchar_t‘ structures, each of which is 16 bits wide, not 8 bits wide. There is also the difference to know, between ~16-bit Unicode~, which actually refers to UTF-16, I think, and  32-bit Unicode, the latter of which would be invoked with ‘U"Some Text"‘…

If a programmer is explicitly using the “Standard Template Library” (‘STL’)… ‘std::map<>‘ construct, then one of its valid forms is, ‘std::map<string, int> myMap;‘. An object called ‘myMap’ is created on the stack, that maps from specific strings, to integers. Because the STL is so strongly based on C++, it’s important to understand that the template instantiation used here, refers to a ‘C++ string’ object at all times, for which reason ‘#include <string>‘ must also be given. Yet, other functions that are strictly C exist, such as ‘dlsym()‘, which expects that its second parameter be a(n 8-bit) ‘c_string’, which can just be typed into the source code. Well, the C++ string class implicit in the template instantiation ‘std::map<string, int>‘, can also be invoked, by typing ‘myMap["Object1"] = 12;‘. What happens in this last case is, that “Object1″ starts out as a c_string, due to the legacy of what the compilers do, but it will get used within ‘myMap’, to initialize a C++ string object. The appearance of the code doesn’t make this obvious. (:1)

But, just to prove that sometimes, it’s okay to put C into a C++ program, one thing which a programmer is eventually allowed to do is, to overload the default ‘new‘ operator, with his or her own version, which will be applied to specific classes of objects. When a programmer does this, most likely, they will have something similar to a ‘malloc()‘ function-call, in the definition of the custom ‘new‘ operator, in any case, probably C and not C++. And, doing so also requires, that such a programmer overload the ‘delete‘ operator… This type of programming opens a can of worms, in the question of how this custom ‘new‘ operator, or its counterpart, the custom ‘delete‘, are supposed to behave, if the constructor call or destructor call throw an exception, and, how to define this behaviour, when defining a custom ‘new‘ and ‘delete‘. Defining these should not be undertaken, unless the programmer who does so, has studied that specific question. (:2)

(Updated 3/14/2021, 0h55… )

Continue reading What the name of the memory allocator is, under C++.

The ubiquity of memory leaks in GUI applications.

When I was studying C++ as an Independent Student, we were taught that, as a good programming practice, we should always delete any objects which we had created with the ‘new’ allocator, including, to do so in the destructor of any objects, which created those members in their constructor. Just to define a little bit, what this means, I need to state some facts:

  1. In C++, we can declare objects to exist as such, without using ‘new’, and without initializing object pointers to point to them. When we do so, they are allocated on the stack, their constructors are called in turn, and, when our function call returns, the compiler makes sure that the stack is cleared, at which point the compiler also makes sure that the destructor of such objects is called automatically. In much programming, including GUIs that we build with Qt5, this is considered to be the less-favoured way to do it by default…
  2. As an alternative, we can declare a pointer to a class object to exist. This pointer could reside on the stack, or, it could be a member of the class, and thus, be a property of each object. Regardless of where this pointer has been put, we call ‘new’ to create a new object, and the address returned by ‘new’ is stored in the pointer, by our own explicit code, either in the constructor if the pointer is a class member, or elsewhere if the pointer has been created in the middle of a function-call.
  3. The pointer, a member of the class, might just receive an address from someplace else, thus pointing to an object that was allocated by a different object, in which case it’s the responsibility of the object that originated the pointer’s address, also to destruct the object it points to… This can lead to issues because, if the object that created the object being deleted does so, the other object will still hold an address, which does not get updated (at least, using plain-old C++ pointers, not, smart-pointers). And then, such a copied address might erroneously be used again, creating nasty error messages and crashes.

The problem with scenario (2) above is, that even though the pointer will get removed eventually, during program execution, the object that it points to, will remain by default, unless we call ‘delete’ on the pointer, in which case the destructor will be called on the object pointed to, and then, the space the object occupied is deallocated. There are finer points to how all this should be done, which are taught in C++ programming, and which I will not get into here. But a point which I want to make in this posting is that, when using certain GUI libraries, including Qt5, the programmer is creating many C++ objects, including widgets, layout managers, labels, QString objects, and eventually also, brief message-boxes…

The programming style encourages sloppy programming, in which not all objects that have been created, are also destructed and deallocated eventually. Admittedly, I have also fallen victim to this, in recent exercises I assigned myself, outside any formal learning environment. And of course, always conscious of the possibility that I could be making mistakes, I have found several.

The lessons I was given formally taught us, to be so thorough in deallocating, that we should even do so when our program quits. This is good form. But, when creating my Qt5 projects, I have not been doing this. Instead, what I’ve been doing, is to distinguish between two types of memory leaks:

  1. Objects that are not deleted when the program quits, meaning that my main application window possesses a destructor which does nothing,
  2. Objects that will need to be deleted, because they were members (properties) of other objects, which might be specialized windows of my application, or which might otherwise be created and deleted many times, during one execution of the application.

 

(Updated 9/03/2020, 14h20… )

Continue reading The ubiquity of memory leaks in GUI applications.