Archive for the ‘programming’ Category.

Goodbye, dmr…

#include <stdio.h>

int main ()
{
    printf ("goodbye, dad.\n");
    return 0;
}

VN:F [1.9.13_1145]
Rating: 9.7/10 (6 votes cast)
VN:F [1.9.13_1145]
Rating: +7 (from 7 votes)

C++11?

The C++0x standard has been approved by ISO/IEC. This probably means that we’re going to be calling this iteration of the language C++11.

It amazes me how much of the language and the standard library people don’t use already. And I mean the C++98 stuff that has been around for 13 fracking years! True, there are professional developers that decide to use a specific subset of the language, or in some situations some design decisions are “inherited” by programmers working on an existing body of code… but I’m not bitching about them (much!) I’m talking about programmers and their new projects and sample code. New programmers (usually university or high school students) don’t learn about most of C++ because their teachers don’t know them and that almost all programming books on C++ suck (sometimes, it’s not the author’s fault; C++ is just too vast and complex.) More “experienced” programmers usually learn about a subset of the language and form a “comfort zone” and stay in there; because anything out of that zone will upset them. The bad thing is that this C++ comfort zone is – more often than not – way too small.

It might (or might not) include good polymorphism and class hierarchies (which I don’t like, incidentally) but almost always it does not include any meaningful use of generic programming, higher order and (some vestiges of) functional programming, attention to memory and layout (I believe many non-trivial programs have ran or are running into address-space limitations as we speak,) exception-safe and exception-correct programming, development of domain-specific mini-languages, real scalability and thread-correctness, etc.

Of course, everybody is free to program the way they want or can. I’m not the one to judge. All I’m saying is that even in the single language we use, there is much that we don’t take advantage of (let alone using other languages that might be more suitable for a job.)

Now, enters a new and feature-rich standard of C++ into an already starved expertise pool. There are so many real features and improvements in this iteration of the standard that they could overwhelm at the first glance. There is (just off the top of my head) r-value references and perfect forwarding, lambdas, variadic templates, compile-time constant expressions, user-defined literals, better enumerations, typedefing templates, initializer lists, better control over inherited methods, better control over compiler-generated class methods, finally some semblance of class- and method-specific directives (alignment, etc.,) extern templates, forwarding constructors, initializing class data members upon declaration, auto and decltype keywords for type inference and whatnot, (oh, I almost forgot!) the cool and hip new way of declaring the return type of a function, and much more.

The above features are just the ones that I could recall right now and in the core language only. I need and want to use these features, additions and improvements right now. They all make my code better and my life easier. These are not some obscure features for practitioners of “black magic”. They benefit the likes of you and I, not language lawyers, but people with real applications and real problems.

I guess what I’m saying is that as a C++ programmer, you should not be afraid of experimenting with the new features today. Don’t wait for the books or libraries and frameworks to pick them up. Books will take years and they will be all wrong and useless anyways (of course, with a couple of stellar exceptions.) Again, only with a few exceptions, libraries and frameworks will be burdened with incompetence, corporate politics, backward and forward compatibility and compiler compatibility (with the most brain-dead compilers. Please don’t rely on Qt or wxWidgets or whatever to do your C++ for you. Please don’t wait for Deitel and Deitel to teach you C++.

Start with Wikipedia. Read various texts and tutorials and overviews that uncle Google finds for you. Start experimenting and teaching yourselves the new features of C++11; and any of the old feature-set that you might be rusty about. It’s a great time for C++, as it is now a better language than it ever was. It’s probably the best general purpose programming language out there for people with actual hardware limitations on their applications. And it can do practically everything. (Also, C++ supports the widest range and mixture of programming paradigms of any programming language that I know of.)

Notes: I have three points to add to the above rant.

First is about the advancements in the standard library. They are much more substantial and accessible for the lazy programmer (I don’t use the term “lazy programmer” as a negative phrase!) as most of the additions are already available with the most popular compilers, or even in Boost if your compiler doesn’t have them yet or if you don’t like your compiler vendor’s standard library! I’m much less enthusiastic about the new C++ standard library features simply because most of them have been available as part of Boost for years and therefore are hardly new. Still exciting, though!

Second. No compiler that I work with has support for all or even most of the new core language features, although GCC is close (not to “all”, but it is close to “much”.) The state of support in Microsoft’s Visual C++ is closer to pathetic. Intel C++’s condition is not much better either. A partial table of the state of support for various new features of the language across quite a few compilers can be found here. Right now, I (and probably everyone else) would suggest using GCC. Get your hands on 4.7 if you can, or use 4.6 or even 4.5. Good luck!

It seems that I’ve forgotten my third note! Maybe it’d come to me later.

VN:F [1.9.13_1145]
Rating: 10.0/10 (4 votes cast)
VN:F [1.9.13_1145]
Rating: +3 (from 3 votes)

Of Pursuit of Programming in Universities

I was reading this post on the AltDevBlogADay and noticed how similar it was to my own experience. The writer’s point is how removed most of academia is from the real world (at least in the programming world) and he relates a couple of anecdotes from his own past. It’s a short and funny read (specially the part about the floating-point number format in memory. I mean, talk about bad bad misinformation, not to mention the idiocy!)

Anyways, near the end of the post, he mentions that he somehow figured out that all the things his professors said were not the truth, the whole truth and nothing but truth. I remember exactly how and when this happened to me.

It was the first semester in my university (which was an absolutely mediocre one.) In the software engineering program over there, there was an “Introduction to Programming” for the first semester, and an “Advanced Programming” (or something like that) course for the second. Back then (in 1999) they taught Pascal in the introductory course and C++ in the advanced. My Pascal teacher was a young guy. A pretty decent teacher and academic (and quite orderly!) Those days, the way to program in Pascal on DOS/Windows and not get into the whole mess of Object Pascal and VCL was to use Borland Pascal (or Turbo Pascal,) which ran on DOS and was primarily targeted to that platform. Not that this was a bad thing, because most (almost all) of the students were unfamiliar with UNIX and programming for Windows was… well, is a mess.

Anyways, when he was teaching Pascal, he mentioned a few times that if you do this or that, the compiler will issue warnings. This was a bit puzzling for me, since I had been using Turbo Pascal for 3-4 years then and I had never seen anything like warnings being issued by the compiler! It either gave errors, or it compiled the code happily. It should be obvious for any programmers in the audience what the problem was by now, but of course, before then I had never actually written any C/C++. My experience was limited to some BASIC variants (Commodore, GW, Q, Visual (shudder),) Pascal and some Assembly. But I was beginning to dabble in C, in anticipation for the next semester and it suddenly became obvious to me that our instructor did no Pascal programming himself. He just had C experience and had read some books on Pascal!

There were many more incidents like this with many more teachers; little mistakes that would absolutely never happen if they had any real experience, and not book knowledge. (I should mention here that not all my teachers were like that. Some of them were surprisingly on top of the subject they taught, e.g. the white-haired 60-year old associate professor who taught Assembly!) I started resenting some of my teachers for their blatant ignorance and shamelessness. In time though, I learned that all of them knew stuff that I didn’t know and could learn. That’s when the university became much more tolerable. I only had to treat all important information the same way: with a grain of saltdoubt, no matter the source.

VN:F [1.9.13_1145]
Rating: 7.3/10 (7 votes cast)
VN:F [1.9.13_1145]
Rating: +1 (from 3 votes)

Fibonacci Numbers and Bad Teachers

Recursion is a fascinating and essential idea in mathematics, programming and design (among other things.) As a programmer, if you don’t understand this very simple idea (and I mean really understand it) you are pretty much done for. While it’s not a hard concept for any half-intelligent person to grasp, I don’t exactly know how many of us really do grasp it. But it’s not what I’m going to bitch about today.

In programming courses, one of the first examples used to introduce the idea of recursion is the Fibonacci sequence. You know, the series of integers starting with 0 and 1, where every next number is the sum of the two previous ones. (OK, I know that you do know. I was just covering all my bases.)

Anyways, the most simple and elegant introductory way of implementing a function that returns the nth number in the Fibonacci series goes something like this:

1
2
3
4
5
6
7
// Just making things clear!
typedef unsigned long long Integer;
 
Integer Fib (unsigned n)
{
	return n < 2 ? n : Fib(n - 2) + Fib(n - 1);
}

And every half-descent programmer knows that that’s probably one of the worst ways you can implement the idea. I’m not kidding. The teachers just throw this at the students, and the brighter of the students see the elegance and simple beauty of it and it will take years for most of them to realize the problems with this particular implementation. Some of them never do. This implementation performs very poorly for even the small values of n, which of course should be apparent when you contemplate its time complexity and recursion tree (I won’t go into space considerations, because they are not much of a problem until n goes into (many) thousands, at which point the value of the function becomes larger than you can store naively in most languages, which means you should have already given space considerations a serious thought.)

But even later, when the students learn about complexity analysis and Big O notation and crap like that, more often than not, they fail to apply the newly acquired knowledge to the old beliefs. If the teacher is good, and the student is bright and lucky enough, they walk out of their algorithm and data structure course with the new belief that bubble sort is bad, hash tables are good, and disk seek times dominate everything else (all of which are obviously bullshit in the absolute sense.)

For the more astute reader, I need to clarify that the badness of the mentioned implementation stems from the fact that most common languages (including C++) are mainly side-effect-driven languages, in that they rely mostly on the side-effects of expressions and statements to get the intended job done (the usage of the term “statement” is a clear sign of that.) Otherwise, you wouldn’t see so much assignment in our code. A functional and side-effect-free programming language (or more accurately, programming model) could easily cache the result of each invocation of the Fib function for any particular n (because the function call would be without side effects and therefore time-invariant) and would not need to evaluate any Fib(n) more than once. This is something that is being done in some of the better implementations of functional languages, AFAIK.

To emulate this behavior in this case, one can use a hand-coded version of what is known as Memoization, a la:

1
2
3
4
5
6
7
8
9
10
11
12
13
Integer Fib (unsigned n)
{
	static std::vector<integer> Mem;
	if (n < Mem.size() && 0 != Mem[n]) return Mem[n];  // The second condition is redundant, right?
 
	Integer ret = n < 2 ? n : Fib(n - 1) + Fib(n - 2);
 
	if (n >= Mem.size()) Mem.resize (n + 1, 0);
	Mem[n] = ret;
 
	return ret;
}
</integer>

This is not a bad implementation. It does have some issues in multithreaded applications, but I'm willing to overlook that for now. This implementation is linear in both time and space, and it can be faster than simple non-recursive implementations because it never calculates any Fib(n) more than once over the whole lifetime of the process. But it's not pretty (it has its charms, though!) and this way of doing things is error-prone (because you are adding memory and bookkeeping to a mathematical construct that is otherwise free of this stuff.) Not to mention that it is basically impossible to use as an introductory example; because it needs knowledge from all over the map.

A better implementation might be:

1
2
3
4
5
6
7
8
9
10
11
12
13
std::pair<integer , Integer> _fib (unsigned n)
{
	if (n < 2) return std::make_pair(n, 0);
 
	std::pair<Integer, Integer> Fn_1 = _fib(n - 1);
	return std::make_pair(Fn_1.first + Fn_1.second, Fn_1.first);
}
 
Integer Fib (unsigned n)
{
	return _fib(n).first;
}
</integer>

Of course, the meat of this implementation (such as it is) is the _fib function. The other one is just there to present a nicer and more consistent interface. Let me be the first one to say that there are more ways to implement a better Fibonacci and still stay essentially recursive. This is just one way, and not a particularly great one. But it's not bad either.

Now, how come no programming instructor ever teaches the likes of this implementation? Not the ones I studied under, at least. Are they afraid that their students' heads are going to explode? PROGRAMMING IS HARD PEOPLE! If a programmer can't handle a substantial improvement over a bad implementation of a simple idea, they are in for a big (and not at all nice) surprise. I hereby beg any teachers, instructors, professors and whatnot that have anything to do with teaching starting programmers to quit treating them like idiots, because idiots won't make good programmers. The idiots are not going to understand what they need anyways, so why take the chance of profound understanding from those who have the capacity to learn, but might not if you treat them like babies?

For the sake of completeness, here's a non-recursive implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
Integer Fib (unsigned n)
{
	if (0 == n) return 0;
 
	Integer last = 1, penultimate = 0;
	for (unsigned i = 1; i < n; ++i)
	{
		penultimate += last;
		std::swap (last, penultimate);
	}
 
	return last;
}

This is the fastest of implementations offered here, with the exception of the memoizing one (and only in amortized sense.) But nothing prevents us from applying the memoization technique to an iterative implementation as well, albeit not in a general and automatic way. It might not be apparent or significant in such a simple sample, but for some class of problems, recursive solutions are usually easier to devise and understand, and therefore easier to get right. In any case, nothing is clear-cut when it comes to programming, and I'm almost offended when people (specially people who should know better) behave as if almost everything is.

VN:F [1.9.13_1145]
Rating: 8.0/10 (6 votes cast)
VN:F [1.9.13_1145]
Rating: +2 (from 4 votes)

An ABSOLUTELY Unmissable Talk on Modern Hardware

Iff[sic] you are a programmer, if you don’t do anything else even if you don’t eat and even if you don’t shower, please please please please please watch this presentation.

The presenter is Dr. Cliff Click, and the topic is an in-depth view of modern code execution architecture. The talk is from 2009, and it has been on my to{do} list for almost 6 months. It is the best thing I have seen in the last year (and I played God of War III!) if not in many years. The guy is obviously very knowledgeable and he talks extremely fast, which just means that he packs an incredible amount of invaluable information into this 50+ minute talk.

I can’t stress this enough. Take an hour to watch this. Please! If you are a game developer, or any programmer with a conscience, you have to watch it right now! I’m not kidding here. Watch this through.

On an ego-boosting note, I just watched this talk and I already knew almost all of it (I have to brush up on the newer cache-coherency protocols though; those have also been on my to{do} list for some time now!) It did have some eye-opening “Aha!” moments for me. I may write about them later.

What are you doing still reading my shithead rant?! GO WATCH THIS!Cliff Click’s Crash Course in Modern Hardware (hosted locally.)

VN:F [1.9.13_1145]
Rating: 10.0/10 (5 votes cast)
VN:F [1.9.13_1145]
Rating: +4 (from 4 votes)

.NET and I

I learned C# in 2000, when the compiler and tools were still in beta (I think. I know I was working with the beta, but maybe the finals were released unbeknownst to me (hehehe! The Firefox spellchecker does not recognize “unbeknownst”!))

I remember that I liked the language. It was clean and relatively compact, it had a largish and useful library, it was like C++ and Java (benefit? really?) and it had a command-line compiler. My impression at the time was that it was more suitable for small and quick programs, and very suitable for teaching programming. I even suggested it to my teachers at university as a replacement for Pascal, which was then thought as the first language to CE students (this was maybe 4 years before I met Lisp, or better yet, Python.) This was also before the whole .NET fucked-up-ness happened with all the WinForms and ASP.NET and whatever other shit they are peddling these days. In those days, .NET and C# produced console applications, unless you ventured into the river of diarrhea output that is the Win32 GUI API; but that was pretty much what you generally had, back then.

Anyways, my shallow and brief delving into the world of .NET was barely deep enough for me to familiarize myself with the inner workings of MSIL and the JIT compiler and the virtual machine. I learned little about these, and I have not kept up with the new developments in .NET, and I have no regrets there. I generally hate GUIs and network technologies that aim to solve all problems on all levels for everybody. They may suit some, and I have absolutely no doubt that many .NET-based applications wouldn’t have been as easy-to-write for other libraries and runtimes1. But I don’t generally like .NET and this opinion (I suspect) would be very hard to change.

The most obvious reason for this obvious dislike is the one I mentioned above. .NET is the champion of the all-for-all thoughtcrime. More than anything else that I have seen, it tries to do all for everyone and everything; without giving them an inkling of what the hell is really going on on any level below the most superficial. This may suit some, but it shouldn’t.

I seriously believe that every programmer needs to know what’s going on under the hood. Total abstractions almost never work beyond the most simple and trivial cases2. If you don’t know jackshit about your platform and your programs seem to have worked so far, you are just lucky. Let me give you an analogy. If you don’t know anything about how cars work and you drive one, when your cars breaks down in the middle of nowhere and you have no means of communication, the you are royally fucked. The fact that this has not happened so far, it just means that the Random Number Gods have smiled upon you so far. It may never happen, but it just as well might. That’s the way it is with programming. Except that the level of quality discrepancies among software and hardware products that you use is much wider.

All programming languages abstract the platform in some form and manner. But as some languages hide not much and what they hide, they do with much shame and much apologies (Assembly, C, etc.) others do as much as they can to distance you from the hardware. They even boast this feature!

In short, every good programmer that I know and I know of knows the whole stack of software and hardware underneath deeply and intimately. In fact, it might even be true that the better they know this mess, the better they are3.

Let me conclude now. I am not saying that technologies like .NET and Java and all those “high-level” languages are useless. I’m just saying they make it harder to be conscious about the actual platform and the rest that lies under your code. I’m pretty certain that the best .NET programmers can pretty much generate the MSIL code and the machine code that their compiler and the JIT compiler generate for any given part of their code. Maybe you should too.


1: Note that I don’t use the word “platform” here, and any other use of the word for a software technology in unintentional and a result of the force of (a bad) habit. No software is a platform; hardware is. It’s always the hardware that runs the code, and the hardware is always the platform. If you think otherwise, I believe you are the subject of the same kind of conditioning that has affected most of us.

2: Read this post on Joel Spolsky’s great (yet now sadly dormant) blog for the original presentation of the Law of Leaky Abstractions. Also read the Wikipedia page (and then the talk page for an interesting discussion.) Also read this Coding Horror post for a hilarious (well, not really!) example. Fuck LINQ!

3: I don’t believe that it’s this knowledge that they acquired first and it magically made them good programmers. I think on the way of becoming good, they had to acquire this knowledge. I have to ponder this a bit more.

VN:F [1.9.13_1145]
Rating: 8.0/10 (5 votes cast)
VN:F [1.9.13_1145]
Rating: +3 (from 5 votes)

There Should Be Dancing Around a Bonfire!

This should be no news to anybody who has anything to do with writing and distributing C/C++ applications on Windows, but Microsoft has finally decided to drop the fucking SxS shit for Visual C++ 2010 CRT and go back to the sweet old days of plain, distributed-alongside-your-application DLL files! (Read here if you don’t believe me! I don’t know how far one can trust MSDN and how long that link will stay valid (I mean, how hard is that?! Keep your stupid fucking links valid, you idiot douche bags!) but there it is for now, and I have verified it on VC2010 RTM.)

How fucking twisted is that?! I’m actually rejoicing because we are going back to DLL Hell! But after experiencing the abyss of WinSxS Hell, I would happily crawl back to the open and only mildly tormenting depths of the good old DLL Hell. This means that I will (hopefully!) never ever have to mess around with ass-busting manifests and colossally subtle version conflicts and hunting down every single gods-damned version of every single fucking-gods-damned CRT component that might or might not have been subject to some whimsical patch by the morons at Microsoft in the past year, in one or other version of Windows. This means that I will just distribute the fucking version of the CRT that seems to barely work alongside my applications (that is, in the same directory) and it will probably (say 30% instead of 1e-10%) work, and no one will be able to override their usage behind the poor hapless user’s back (using conventional methods; that is. Everybody knows how easy it is to hijack a function call into a DLL in Windows; which I have to say is not necessarily a bad thing.)

And don’t anyone dare ask me why I link to CRT as a DLL in the first place, instead of a statically linked LIB!

P.S. I have decided to write as I think (regarding the usage of curse words.) So no more fraks and friggins and butts and backsides. Deal with it.

VN:F [1.9.13_1145]
Rating: 8.3/10 (6 votes cast)
VN:F [1.9.13_1145]
Rating: +2 (from 4 votes)

A Lesson in “Test” Attitude

Back in the old days of the net, even before I was born, people did implement TCP/IP stacks. And since there weren’t much of a solid and standard specification (not to mentions decades of engineering experience in implementation and maintenance of network stacks,) these implementations tended to be buggy, unstable and non-conforming. To test these various TCP/IP implementations (such as they were,) people used to come together and just test them against each other and compare their functions. These sessions and discussions and reviews were called “TCP and IP bake offs”. It has been said that as a result of these discussions, the specifications were as likely to change as the implementations!

These dudes pretty much built the whole frakking Internet without the bureaucracy and the 3000-page conformance guidelines and the 2-million line test suit or the 12 years worth of committee meetings. Their procedures, and much more importantly their attitudes is quite concisely demonstrated in RFC 1025.

VN:F [1.9.13_1145]
Rating: 8.7/10 (9 votes cast)
VN:F [1.9.13_1145]
Rating: +4 (from 6 votes)

“Planning for Debugging Day” Presentation

Here are my presentation slides from the talk I gave this past March in Sharif University, at the first Iranian computer game developer’s mini-conference.

Here I talk (mostly out of personal experience) about things that we should pay attention to, at the beginning of a game development project, so our debugging and issue tracking and solving experience becomes less irritating and more effective. I’d be happy to hear any suggestions, corrections and discussions.

Oh, and I have expanded the talk a bit, from what I actually presented! Also I’d be happy to explain my views on any of the particular points if anyone actually bothers to read through the thing.

VN:F [1.9.13_1145]
Rating: 8.2/10 (5 votes cast)
VN:F [1.9.13_1145]
Rating: +4 (from 6 votes)

The Human and the Machine

I was watching George Dyson’s interesting presentation at TED about birth of the digital computer, and something rather frightening occurred to me.
When I started out with computers, maybe 18 years ago, I was in awe of them. Computers and what they did were a closed book to me, the way a great musician’s work is shrouded in mystery for me, yet I was enjoying their output and imagining what else they would do. Pretty much everything surprised and delighted me. As I grew more familiar with their working and started writing code, my awe remained but it also transformed, to a kind that maybe a musics student feels when seeing a true master play.
The awe and delight pretty much remained as I grew closer and closer to the machine, I knew more, but it still was like seeing a loved one achieve a great accomplishment or part of a great orchestra that plays a fantastic piece. Seeing beauty even from inside inspires awe. Of course, I’m not suggesting that I was any good at any time, merely describing what I felt.
In general, it was a like a love affair. Every little things, even the hiccups were strangely endearing. I wouldn’t think of computers as a machine. Of course, the hardware is a piece of dead equipment, but there is something else in there and I think I felt it. The Ghost in the Machine. I was in love with the ideas behind the hardware. I never thought of myself as a master of the machine, or it just another tool like a can opener or something. We were conversing with each other and we took nothing for granted. If something didn’t work, it was neither my fault, nor its; the problem was in the communication.
But then my view started to change. I started to rely on certain things to work and certain things to go wrong. I started to view the computer as a terminal for information, as a tool for bilateral delivery of entertainment, data, software or communication with other humans. The machine started to get transparent in the process, the way your door is a transparent method of getting in and out of your home. The door is there, and you know how to use it, but the door itself is not at all important. The stuff and places on either side is what is important.
This change kinda creeped onto me. Today I was forced to think about it, and I was shocked and terrified to realize that most of that awe has shifted from the machine to other people. The machine is no longer there, only those who designed and built the hardware and software. I don’t know how to exactly explain my feeling, and my depiction here is not exactly accurate. But I have lost the reverence for the love of my life, and I am a worse person for it. And I am sadder, and certainly a worse programmer, which is ultimately the most important aspect of my life. Oh, I do write better code and probably design better today than any time in the past, but I am nonetheless a worse coder and programmer, because I have lost the sparkle, and the love and ability to be pleasantly surprised no matter what.

VN:F [1.9.13_1145]
Rating: 7.5/10 (4 votes cast)
VN:F [1.9.13_1145]
Rating: +1 (from 3 votes)

Fun with C++: new, delete and Some of the Rest of the Story

Every C++ programmer knows new and delete and how they work. At least it must be so. I sure as hell didn’t know all the theory and detail behind C++ memory management facilities until 3-4 years ago, and I’m obviously still learning the practical details. So, please bear with me and see if there are things that you can learn about these old pals of ours, new and delete.

First, we all should know that new and delete are C++ operators, with all their facilities (and shortcomings, of course.) But not exactly like other operators, you can override them at a global level for every type that does not provide its own type-specific such operators. These global operators are provided as part of the C++ runtime library and are easily overridden. Their declarations are:

1
2
3
4
5
6
7
// The single-object versions
void * operator new (size_t mem_size);
void operator delete (void * mem_block);
 
// The array versions
void * operator new[] (size_t mem_size);
void operator delete[] (void * mem_block);

What new does is allocate a block of memory, and then call the constructor for the type with the address of the newly allocated block passed in as the this pointer. A delete call does the reverse; calling the destructor and then de-allocating the memory. The difference between the single-object versions and the array versions is only in the number of c’tor/d’tors they call. It amazes me how many C++ programmers don’t know and don’t care about details such as this (if you are programming in C++, these kind of details can and will bite you in the places you don’t want to be bitten!) If you fail to match them correctly, they allocate and de-allocate the correct amount of memory for the array or the single object, they just might not call constructors and destructors for all the objects being allocated or freed. That’s it.

Also, there is that small detail about exception-handling handling (yeah, two “handling”s!) The new operators may only throw an object of a sub-type of std::bad_alloc and only in the event that the requested amount of memory cannot be allocated. delete operators should never throw any exceptions (just like destructors. Remember that!) So, the correcter declaration for these operators would be:

1
2
3
4
5
6
7
// The single-object versions
void * operator new (size_t mem_size) throw (std::bad_alloc);
void operator delete (void * mem_block) throw ();
 
// The array versions
void * operator new[] (size_t mem_size) throw (std::bad_alloc);
void operator delete[] (void * mem_block) throw ();

Again, it is amazing how many programmers either don’t know about function exception specification and exception safety or just don’t use them (that includes me.) Of course, compiler providers are at least a little to blame here too. For example, Microsoft C++ compiler only distinguishes the empty exception list after a function declaration (meaning it doesn’t throw anything.) Anything else put there, just is taken to mean the default behavior is used (i.e. this function does throw something sometimes.)
In the meantime, the relationship between C++ programmers and exception handling remains in the love/hate/ignorance/hate/apathy/hate stage.

Later on, I’m going to talk abut overloading these global operators for fun and profit. Stay tuned! ;)

Obviously, a related problem to memory management is calling the c’tor and d’tor for an object directly. Uses for this may not be immediately apparent, but as a few examples I could name implementing good smart pointers, memory pools, memory managers, garbage collectors, generic object containers (e.g. std::vector) and such.
You probably already know how to call the destructor on an instance directly. If you have a pointer x to an object of type T, you can call its d’tor like this: x->~T() (note that you should not generally call the d’tor in this way, unless you yourself have called the c’tor directly on that instance as well.) Calling the constructor is a bit trickier though (not really; I’m just being foreboding!)

What you should realize is that you can overload new and delete with different signatures that the ones above. You can add arguments and of different types. There are a few other signatures for these two provided by the standard C++ library (yeah, there are others!) The less interesting of them are:

8
9
10
11
12
void * operator new (size_t mem_size, std::nothrow_t const & please_dont) throw ();
void operator delete (void * mem_block, std::nothrow_t const & please_dont) throw();
 
void * operator new[] (size_t mem_size, const std::nothrow_t & please_dont) throw ();
void operator delete[] (void * mem_block, std::nothrow_t const & please_dont) throw();

Forget about the deletes for a minute. The additional parameters to the new calls above are actually not used inside of the functions. Any object of type std::nothrow_t will suffice as the second parameter; it will be there just to signal the compiler to use this particular overload of the operator, which doesn’t throw any exceptions whatsoever. I just need to emphasize again that the regular new never returns a NULL pointer. It just throws an exception. But this one returns a 0 pointer upon failure and never throws anything, being it rocks, shoes or exceptions. The syntax for calling them, as you might suspect, is peculiar:

13
14
15
16
17
18
19
20
21
#include <new>  // for std::nothrow
//...
T * p = new (std::nothrow) T (/* usual constructor parameters */);
// The line above calls a particular "new" overload with two
// parameters: a size_t and a std::nothrow_t.
// Oh, and std::nothrow is just an object of type std::nothrow_t.
//... 
delete p;
</new>

Notice that I didn’t call the delete with any extra parameters or anything. In fact, there is no syntax in C++ for calling delete with any parameters! Besides, delete is already a non-throwing function. So what gives?! Why is there a paired delete for every frakking new when there is no frakking way of calling them?! You should keep your cool. I may explain them (if you don’t already know,) or we can leave the subject as an exercise. I would just say that the paired delete is called by the code generated by the compiler in a very specific situation.

Note that anything other than the straightforward, unary new and delete is called a “placement new/delete“. However, I’ve heard the term be used for a specific overload, which is more interesting and looks like this:

21
22
23
24
25
void * operator new (size_t mem_size, void * mem_ptr) throw ();
void operator delete (void * mem_block, void * mem_ptr) throw ();
 
void * operator new[] (size_t mem_size, void * mem_ptr) throw ();
void operator delete[] (void * mem_block, void * mem_ptr) throw ();

The implementations for the above operators are really simple. Here’s a complete listing:

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void * operator new (size_t mem_size, void * mem_ptr) throw ()
{
    return mem_ptr;
}
 
void operator delete (void * mem_block, void * mem_ptr) throw ()
{
}
 
void * operator new[] (size_t mem_size, void * mem_ptr) throw ()
{
    return mem_ptr;
}
 
void operator delete[] (void * mem_block, void * mem_ptr) throw ()
{
}

Note that although I haven’t written it, the constructor and destructor calls happen outside of my control. These versions of new and delete are used when we don’t want to allocate or free any memory, and just want the constructors and destructors to be called. For new, we just pass in a pointer to another sufficiently-sized memory location and ask the compiler to generate the code to call the c’tor upon that area of memory. That’s how we call a c’tor directly. We procure some memory area from somewhere and use that, like this:

43
44
45
T * x = (T *)malloc (10 * sizeof(T));
for (unsigned i = 0; i < 10; ++i)
    x[i] = new (x + i) T (/*usual c'tor params. */);

These standard placement operators cannot be hidden or overridden in user code, but there is still a ton of fun to be had.

You can very easily replace the old, simple and default operators with an implementation of yours, a la:

46
47
48
49
50
51
52
53
54
55
56
57
58
59
void * operator new (size_t mem_size)
{
    void * ret = malloc (mem_size);
    if (0 == ret)
        throw std::bad_alloc ();
    return ret;
}
 
void delete (void * mem_block)
{
    free (mem_block);
}
 
// the array versions are exactly the same

As I have stated earlier, the c'tor/d'tor calls are generated automatically for you by the compiler. So now you are free to write your own memory manager!

The way that memory manager/debugger/helper/whatevers usually work under the hood is that they allocate more memory than you have requested, and put their own junk right before and/or right after the area that gets passed back to the user (that's a bad way to do memory management, but that one is a long story.) Some of the stuff that are usually kept there include a pointer to the next and/or previous allocated block of memory (so all the blocks form a linked list,) sentinel values right before and right after the user area to detect buffer overruns (e.g. 0xdeadbabe,) the size of the memory block, the code file/line/function/module that allocated this particular block and so on and so forth. Actually, your default memory manager in the CRT is doing this right now. Just new two large-enough blocks of memory and compare their address differences with the size of the first block. The runtime accompanying some compilers (like VC++) even exposes their internal data structures and means to work with the memory manager (although rather passively.)

You need to keep in mind though, that what I have discussed so far barely scratches the surface of writing memory managers. These are just practicalities and implementation details; the state of the art on the theory of the matter and memory allocation algorithms, policies and mechanisms can fill several books. Even on the implementation side, there are really serious issues with performance, cache-friendliness, thread-safety, multiple thread support, etc. need taking care of.
Besides, much (if not most) of the memory (de)allocation going on in a C++ program these days go through C or operation system API, shared object files (DLLs,) through third part code or through STL, all of which bypass the basic technique discussed above. So, if you really are serious, you should investigate the existing memory debuggers or memory leak detectors or memory managers. There are several open source ones out there, with various degrees of sophistication and complexity. Have fun! (But for what it's worth, I should mention that we have used a memory leak detector using nothing but this technique in Garshasp and a similar project before, and in both projects it has been a great help.)

VN:F [1.9.13_1145]
Rating: 8.0/10 (11 votes cast)
VN:F [1.9.13_1145]
Rating: +3 (from 7 votes)

Time, Only Time

I have a post about measuring time in a game engine on the Grashasp Dev Blog. Give it a read if you have the time and you are interested.

VN:F [1.9.13_1145]
Rating: 7.0/10 (4 votes cast)
VN:F [1.9.13_1145]
Rating: -1 (from 1 vote)

Fun with C++: Function Try Blocks

C++ is complex. That might sound like an about right to two groups of people – those who don’t know C++ and those who really know C++ – but only those who really know understand the depth of that statement. I’m only beginning to learn C++ and I’m only just learning the depth of it.

Take the following sample code for instance:

1
2
3
4
5
6
void foo ()
try {
    // Some code
} catch (...) {
    // More code
}

As surprising as this might be to some (or not) the above is a valid C++ function definition. That’s right. No regular body in this function.
Now, the skeptics among you might wonder what usefulness this might possibly have! Wonder no longer. The foremost use (and the most straightforward one) is in the context of constructors and correct exception handling.

Suppose you have the following class and constructor:

1
2
3
4
5
6
7
8
9
10
11
12
struct Bar
{
    Bar ();
 
    // Baz is another class that might throw an exception in its c'tor.
    Baz m_baz;
};
 
Bar::Bar ()
    : m_baz ()
{
}

How can you handle exceptions that might be thrown when m_baz is being constructed (e.g to do something useful with them?)
The answer is obviously a try body for the constructor. A la:

1
2
3
4
5
6
7
Bar::Bar ()
try
    : m_baz ()  // Note the "interesting" placement!
{
} catch (std::exception & e) {
    std::cerr < < "'Bar' c'tor is FUBAR!" << std::endl;
}

This has other very cool usages too. For example, to define a macro, with an aesthetically pleasing usage, to track entry into any function (for run-time call graph generation and other analyses.)

1
2
3
4
5
6
7
8
9
10
11
12
#define TRACK_FN                                 \
    try {                                        \
        GlobalFunctionTracker::onFuctionEntry    \
            (__FUNCTION__, __FILE__, __LINE__);  \
        throw (42);                              \
    } catch (int)
 
// Use the above macro like this
void qux (int arg) TRACK_FN
{
    // Do your thang here...
}

Of course, this is not the most efficient way to implement this, but its the most beautiful one!
Some notes:

  1. In effect, we are injecting code into the scope of the function. All the function arguments are available in the try and catch blocks.
  2. If you use this try-block thingy for a constructor or destructor, the exceptions thrown in the try block will propagate automatically beyond the local catch! For all other kinds of functions, this will not happen and if you catch the exception, it will be stifled unless you rethrow it explicitly.
VN:F [1.9.13_1145]
Rating: 10.0/10 (2 votes cast)
VN:F [1.9.13_1145]
Rating: 0 (from 0 votes)