Latest News
spacer View All spacer
 
February 9, 2010
 
Analysts: EA On The Right Track At Last
 
GamesBeat@GDC Confirms OnLive, GameStop, PlayStation Home Speakers
 
Ubisoft Q3 Sales Edge Down, As It Ramps Up Big Franchises
spacer
Latest Features
spacer View All spacer
 
February 9, 2010
 
arrow Television, Meet Games
 
arrow Two Halves, Together: Patrick Gilmore On Double Helix [1]
 
arrow The Road To Hell: The Creative Direction of Dante's Inferno [20]
spacer
Latest Jobs
spacer View All     Post a Job     RSS spacer
 
February 9, 2010
 
Telltale Games
Senior Software Engineer - Core Technology
 
Airtight Games
IT System Administrator
 
Roblox
Apple Game Engineer - Kids' Virtual World
 
Roblox
Senior Web Engineer (front-end)
 
Ubisoft San Francisco
Core Engineer
 
Ubisoft San Francisco
Gameplay Engineer
 
Vicarious Visions / Activision
Audio Programmer
 
Rockstar North
Senior Graphics Programmer
spacer
Blogs

  In C++, Everything is Harder Than You Think
by Neil Gower on 08/14/09 04:05:00 pm   Expert Blogs   Featured Blogs
15 comments
Share RSS
 
 
  Posted 08/14/09 04:05:00 pm
 

I've recently been doing some low level C++ work, the kind of stuff where you have the Standard document open on one screen, and your code in the other. What I found interesting was how complicated relatively simple things become when you're aiming for standards conforming correctness.

To take a basic example, dynamically allocated objects and pointers are simple in principle - allocate with new, remember to deallocate with delete. Oh, except for arrays, if you use new[] then you have to use delete[]. And don't mix malloc and free with new and delete, although they're all available to you. C++ standardsWhy yes you can dereference a dangling pointer, and it might even appear to work for a while.

Uninitialized pointers? No problem, you're the boss. Want to allocate some raw memory and then use it to for objects? You can do that, but if you get the alignment wrong, it might blow up in your face at runtime.

How do you check alignment anyway? Shh.. that's a secret! (Actually, it's an implementation detail of the compiler, which is almost the same thing)

Many of these memory management problems can be solved by smart pointers. But when I read Meyers' comment in Effective STL that his smart pointer class was buggy, I started thinking I might become a full time Python programmer.

The reason for most of the complexity in C++ is that the standard makes very few assumptions about the target system and compilers, and also tries to avoid imposing any extraneous overhead on the program. The STL introduces a good set of higher level functionality, but brings with it more complexity to master.

There are a lot of subtleties in C++ that most of us never give a moment's thought to until something goes wrong. The (More) Effective C++/STL books exist almost entirely to bridge the gap between our everyday understanding of C++ and the details of how it really works.

We don't have to abandon ship and start converting everything to C# and Python just yet though. I was motivated to write this post because I noticed that every time I thought to myself, there must be an easier way to do this, there was - Boost.

I had always thought of Boost for its add-on features like regular expressions and fancy math. However, Boost also takes many of the things in C++ that are good in principle (low level memory management, smart pointers, iterators...) and makes them good in practice.

The Boost community is full of hardcore C++ experts that have worked out solutions to handle even the most obscure scenarios that C++ presents, scenarios which most of us will never have the time or inclination to investigate. Boost is nice and modular too, so you can generally pick and choose the bits you want to use.

If you find yourself frustrated writing endless lines of boilerplate code for cases you don't even know will ever happen in your code, have a look through Boost and see if someone has done the work for you. You could be pleasantly surprised. Working in C++ can be great, you just have to bring a full toolbox to the job.

 
 
Comments

Alex Champandard
profile image
"If you have a C++ problem and use boost as the solution, then you have two problems." :-)

I've not found boost to be very modular, it's a monolithic library. Just count how many files you need to include to get smart pointers or delegates.

Benjamin Quintero
profile image
using boost = dreadfully slow compiles + bloat + questionable code generation

I've worked on projects that literally failed to compile because boost overloaded the compilers max recursive includes and pre-processor memory space. It's especially bad if you are using visual studio 2k3 or earlier as their pre-processor peaks are somewhere around 64k i believe. There might be a service pack to fix that but the point is that you should never have to know that the limit existed =).

For basic algorithms and data structures, there's nothing wrong with writing them once and putting them in a safe place for re-use through all your future professional projects. Using vaguely defined common libraries is fine if you are writing a school project or a quick batch tool.

Stephen Northcott
profile image
Most pointer / allocation foobars in C++ can be spotted and cleaned up in 5 minutes by using something like Fluid Studio's Memory Manager. Which AFAIK is free. Good coding practice, once you've learned the rules, is the best protection there anyway.

As for STL containers. I have a love hate relationship with them. I still really don't get why they need to deallocate and reallocate things you stick in them, and for anything I need total control over I generally end up with containers full of pointers, which I then manage myself. Ultimately if it's speed critical code, once I have it working I write a custom class to do the job it was doing. As Benjamin points out these can be ferreted away and used in future projects.

I guess most of my approaches to writing stuff in C++ end up being more like I am writing in C because I am at heart an assembly coder.. But so far every other language I've looked at seems as full of bloat and their own foibles & inconsistencies that I take the "better the devil you know" attitude towards it all.

It has to be said that about a million years ago I thought that I'd pick up C++ in a couple of days. Which I did. What I did not realize is that I would still be learning to use it today!

Neil Gower
profile image
Thanks for the feedback guys!

It's true, Boost does require a bunch of bootstrap files to get started. The bare minimum for smart pointers is a half dozen headers and 3 subdirs of additional boost bits. I don't think that's so bad, but if you prefer something more minimalist, check out Loki: http://loki-lib.sourceforge.net/

Ben, sounds like you had a traumatic encounter with Boost in the past! Today's library is definitely not vaguely defined - many parts of it are included in the work of the ISO standards committee for C++. But over-zealous use of Boost (or STL) and bad use of templates could definitely bloat your code and build times. These problems can be managed by good coding practices. That's not really a fault of the library, it's a feature of C++. ;-)

Imre Chroncsik
profile image
C++ has a different philosophy than most other popular languages (like Java, C#, Python, etc.): instead of giving you ready-made solutions to certain problems built into the core language, C++ gives you tools to roll your own solutions as libraries. That's why it's pretty pointless to compare the core C++ against any other language; if you want a comparison, you need to take C++ together with a selected set of external libraries (hand-picked for the particular problem at hand), and compare that against another language (and possibly libs for that language).

This philosophy makes C++ more flexible, but also harder to learn and use correctly, even if you use 3rd party libs instead of creating your own. Still, this is an approach I pretty much like, and prefer above languages that give you one built-in solution for one problem, and require you to stick with it (if you don't like the built-in garbage collection algorithm, well, pick another language, or at least another compiler; whereas in C++, you can switch to another library), but unfortunately there's one major problem with it: due to different conventions / practices, it's quite frequently a royal pain in the ass to get multiple C++ libraries work together. This is where some sort-of-standard solutions like boost may be of great help.

Dirk Broenink
profile image
C++ is still used for games because it is best used to generate performance heavy code with. As in, it is most efficient when used properly. For smaller applications, especially tools, companies are already using C#. It is easier to make something in it quicker, but is slower.

C++ is complex, and offers a lot of freedom. You are very close to the compiler output, so to say (especially when using SIMD instructions, where c++ almost directly translates into assembly). This is why it's fast, and this is why it's used for games.

One can start using Boost and other big libraries, but I doubt that will still be fast enough (benchmarks will need to shed light on this though). The thing is; the more it supports, the slower it gets.

I understand why the gaming industry uses C++, I think it is a language that is fun to program in, but I try to keep an open mind to C# and libraries. I remain skeptical untill benchmarks compare speed, though.

Robert Allen
profile image
They're all tools. But the analogy I use is that the difference between C/C++ and Java or beyond is this; if you're a mechanic you can either be trained to diagnose symptoms using lower level tools to fix an engine, or you can plug it into a diagnostic computer. The former will eventually fix the problem. The latter can only do what the diagnostic computer supports.

Years ago I worked at a large game company that produced a very large website for casual games. It was made from Java and used an app server. Many Java "programmers" were hired. But since Java was their first language, they new'd up objects as needed with no thought as to whether they could re use the same variable 10 lines later. This overloaded the garbage collection system, so the website ran like molasses under load.

Java was created to run set top boxes originally; it's not (yet) high performance.

C++ is a boon for many things when compared to C. When compared to newer languages it is definitely more primitive. But it is faster as long as you know how things are implemented and don't rely too heavily on using standard classes where base types can be used. I still can't get over how opaque the string class is when compared to just using so-called C strings. The latter requires that you use libc functions to do even the most basic searching or concatenation, but the libc calls that do it are often written in optimized assembly code.

There is no magic. It all comes down to assembly language. Real work has to be done somewhere.

Evan Bell
profile image
I have (at least) two complaints with smart pointers:
1) Can change a "holds a" relationship to "has a" by requiring inclusion of an additional header file.
2) Encourages ignorance about the lifetime of objects.

I often prefer explicit reference counting when an object needs to be "held" by many objects. It certainly is not without its problems though. One moral of the story is higher level, often useful, abstractions don't excuse the programmer from knowing how it works(as Mr. Allen's story relates).

Chris Howe
profile image
To continue the mechanic analogy, I would take my car to the guy with the diagnostic tools. In 99% of cases he will be done in half the time and I'll pay half the labor costs! Of course he still needs to know the lower level stuff for the remaining cases, but that doesn't mean you throw the tools away.

Robert Allen
profile image
Chris, you will be interested to know that the way modern US doctors are being trained is more like the "diagnostic computer" way than the "start with the basic tools" way. Personally I'd rather be treated by the latter.

And the diagnostic car computers can only report on stuff controlled by the engine computer, which means nothing in the suspension, or rear end, or tires, or probably the cooling system, is covered.

Finally, the difference between the car analogy and the language analogy is that more modern languages like Java cannot be used at a lower level, while in C++ I can always go back to libc for lower level interfaces if need be.

Troy Humphreys
profile image
Ben, you just like writing everything yourself. How many times can you write a smart pointer before losing it? :)

Everyone has valid points, I favor getting things done in a shorter amount of time. So I'd lean of the high level languages when possible. We just got to get Mono working on 360 so we can have a decent scripting language on all platforms (Like Howe was saying in his blog).

I'm into using boost and stl when possible. It's not worth rewriting and redebugging your containers and such IMO. Plus more people have used boost/stl than your own rolled code, so ramping people up to your code base is less painful. Also writing containers and other features is a complete waste of time if they are already implemented how I'd want them.

The argument about people miss using features in a high level language applies to every bit of code written anyway. And new employees are more likely to miss use in house code, than industry standard features and libraries. With industry standard features and libraries, the people learn that lesson once, rather than every time they encounter a new system (We'd like to hope at least;) ).

Lastly, Depeche mode is a pretty kick ass band:)

-Troy

Martin Danger
profile image
I think that D is a viable replacement for C++. It's not without its quirks, but it makes a lot of things in C++ much easier. Things like optional garbage collection, static if statements to make template meta-programming much nicer and closures. Yet it's still low level enough that you don't run into any of the Java quirkiness (the Java guys, bless their pointy heads, are language purists, whereas the D guys are academic pragmatists I think).

To be completely fair, I also think that Haskell is a viable replacement for C++, so take this with a grain of salt.

Chris Ledwith
profile image
1) Use Boost and STL whenever possible. They're industry standards and don't require the development time or ramp-up time for new employees (as Troy said)
2) Don't misuse Boost and STL. You can abuse any tool out there. The trick is to leverage the tool's advantages in service of the end goal, which is actually shipping a product (and that has nothing to do with religious wars about programming choices).

All that really matters to the people paying our salary is that, in the end, you have a great game that people want to play, and you get it out on time, and your marketing team did their job. Part of what goes into a game being great, is performance. You can't justify unconventional choices until the profiler on the target platform(s) actually tells you that the conventional choice is slow -- you just can't. If in the final months of a project, the profiler says "this container class is too slow", then you rip it out and produce your own custom container that alleviates that bottleneck.

Troy Humphreys
profile image
D! I have something new to read up on. Anyone actually use this on a game (on the consoles)?

Randy Johns
profile image
C++ is a great language for every reason. In my opinion it should be used for just about everything in a game. I can't imagine doing physics or collision in C#, especially with Mono. It's just not fast enough.

I'm in favor of using C#/Mono for scripting high level game objects, but only so changes can be made and tested on the fly. This pretty much requires a programmer to script the game objects, or a simpler system written on top Mono to allow non programmers to add fluff to the game. I think Smart pointers have their place here, but pretty much nowhere else in a game (because of the overhead).

I like to share code between tools and runtime. For that reason I also use C++ for tools.

Don't get me wrong. I really enjoy C#. It's a fun language, and it's easy to get things done quickly.

But for me, C++ is where it's at for games.


none
 
Comment:
 


Submit Comment