136 comments

[ 0.16 ms ] story [ 193 ms ] thread
Pretty sure Nicholas Vining was referring to the LithTech engine and the game would be Die Hard: Nakatomi Plaza
Yep, this is the comic he was referring to: http://www.penny-arcade.com/comic/2002/02/11
This is actually not the first mention of that character -- that would be this comic[0] -- but seeing as that comic doesn't mention an engine and the rest doesn't really fit either, presumably the one you link is the one he actually meant.

[0] http://www.penny-arcade.com/comic/2001/07/11

Nicholas Vining was referring to the first ever appearance of the character, not its first mention. The Lithtech comic is the first appearance, and the one you've linked is its first mention.
Interesting. Does it not count as an appearance even though its box is there, with the item inside?
I also find it amusing that my favorite multiplayer PC FPS ever was released using the next iteration of that engine... (AvP 2, btw).
I want to do something very violent to that person who "hates const with a passion". No wonder he didn't provide his name.
Casey Muratori considers const a complete waste of time, so apparently that's a thing with some C/C++ programmers.
That is why you should never learn from one exclusive source, especially if they don't provide valid arguments, and imply "trust me".

I saw a couple of his introductory videos and I think he is great to teach specifics about game programming, but should definitely not teach how to write C.

His argument is that he reckons that over his career he made very few bugs that could be avoided if he had used const. He admits that it's specific to his coding style and may not apply to other people.
where did it mention that in the article? I don't see it
The article is in four pages. I missed it at first too.
'const' in C and C++ is broken. Not only is it like a Chinese word that varies wildly in meaning depending on where you use it and how it is inflected, but in C-family languages, 'const' modifies type, making objects that benefit from the compiler hints 'const' implies type-incompatible with objects that do not. This results in the problem of some know-it-all deciding that a core API needs to be const-correct, and checks in changes making it so, only to find that the entire fucking code base is now broken.

Note that I'm not saying "don't use 'const'" with the above (and I'm CERTAINLY not saying "using '#define const' in your code base is a good idea"); only that 'const' in C-family languages has significant drawbacks which may affect the engineering tradeoffs you make when you decide whether to use it.

By contrast, languages such as Ada have explicit and implicit constantness restrictions ('in' parameters, for instance, cannot be modified), but these do not modify the type of the object, allowing objects with these restrictions to be type-compatible with objects without them.

> only that 'const' in C-family languages has significant drawbacks

AFAIK this is pretty much limited to C and C++. Many (and I am willing to venture most, or at least the most-used) C-family languages that aren't C/C++ don't suffer this issue. Go and Javascript, for example, both use "const" in a way that doesn't modify the type of the underlying object.

"C-family languages" here means C, C++, Objective-C and D -- not any of the "look-like-C-but-have-completely-different-semantics" languages, or Go which is probably closer to proposed C replacement Alef than to C itself.
I think that the scope of this discussion is limited to C/C++. If a programmer doesn't like immutability as a broad concept, he is clearly an incompetent imbecile (and I'm trying to write that as polite as possible, given the severity of the issue).
Can you please provide some examples where this really becomes a problem, so I can better understand what you mean?
Everybody who has tried to use const in even medium-sized C++ codebases is familiar with the behavior discussed here. It's not about specific examples, it is about what happens when you have a lot of code.
Can you please provide some examples, so I can better understand what you mean?
If you make a function that accepts an unsigned int, and then you try to pass in a const unsigned int, you will need to either typecast it, make a new function, or change the function to only accept const unsigned ints.

Although it's been a long time since I coded in C/C++, correct me if I'm wrong.

That sounds completely wrong, unless the function takes a reference to the unsigned int.
You're incorrect, for C89 through C++17. I'd recommend not making statements about languages you've forgotten.

In the C++ Working Paper, the Standardese is N4527 5.2.2 [expr.call]/4 "When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding argument." followed by 8.5 [dcl.init] where /17.8 has a nice example:

"Note: An expression of type "cv1 T" can initialize an object of type "cv2 T" independently of the cv-qualifiers cv1 and cv2. int a; const int b = a; int c = b;"

(A "cv-qualifier" is const or volatile; they behave similarly in many contexts, hence the collective terminology for convenience.)

I stand corrected, thank you.
I'm no C nor Ada expert, but I think he means in C `const` is a data type modifier, whereas in Ada it's a function modifier, making the concerns orthogonal. I'm never happy when I see warning about `const` being lifted by some function in C. I think that's what parent is referring to.
I'm someone with a codebase where we practice const correctness and we haven't had a problem with it. We were being const correct from the start so we don't have the problems associated with trying to change that midstream.

Assuming you do it from the start you shouldn't be running in to issues.

Exactly right. But the example was of combining two code bases, one of which tried to maintain const correctness and one which had utter disregard for it. If you don't believe in const correctness in the first place, the work of making your code compatible can seem intractable.
Hmm, I'm not sure if codebase with millions of lines is 'medium' or 'large' but from my experience const is great even there. Of course, modifying existing code to become const correct in interfaces where previously it was not can cascade to a point where a majority of the code needs a rewrite, so I can see situations where adding const to an old interface can cause lots of grief.

But from my experience const really helps in enforcing directed graph constraints on logic and data flow which is great - and forces code to be easier to reason about.

Const, in theory, is a fine idea. As implemented in C++ though, it's unwieldy. There's at least three (if memory serves) places you can put it in a member function declaration (not including params).

What's more, it can "infect" any other code that touches it, in turn requiring casting or weird const additions. For a simple rant, check the first few paragraphs here:

http://www.vaxpower.org/~isildur/const.html

Looks like someone who does not even understand C++ in the first place...
What the author there is calling "infecting" and "mangling" seems to be const doing exactly what it's intended to do.

You can't just declare something a constant then cast it out of being constant later? Of course not, that's the entire point!

No, see, that's the thing. It's annoying when you want to--and I apologize because it's been several years since I had to deal with this nonsense--copy elements between logically compatible containers but ones whose types are differing in layers of constness. Or if you to, say, move a reference all the way down into a pointer (or vice versa) to interop with C or other legacy code.

Or any of several other things, including some truly odd possibilities using operator and function overloading.

It's just really gross as implemented.

copy elements between logically compatible containers but ones whose types are differing in layers of constness. Or if you to, say, move a reference all the way down into a pointer (or vice versa) to interop with C or other legacy code. Or any of several other things, including some truly odd possibilities using operator and function overloading.

And this is 'const''s fault? Others have asked - can you provide an example? Because what you're describing sounds like it's going to be a hot mess, const or no const.

I don't really think that const can make bad data representation any worse than it already is.

It sounds like you wanted to do something like this:

    std::vector<char*> vec1(...);
    std::vector<char const*> vec2(...);
    std::copy(vec1.begin(), vec1.end(), vec2.begin()); // works (1)
    std::copy(vec2.begin(), vec2.end(), vec1.begin()); // fails (2)
If this compiled, the second example would invoke undefined behavior and crash if you attempted to write to an element that pointed to read-only memory (e.g., a string literal).

Container element types are almost never declared const unless their values are truly immutable (in this case the pointer is mutable, but the underlying memory is not, which is kind of strange).

I think he just meant that: void foo(std::vector<char const* > &vec2) { ... }

    ...
    
    std::vector<char*> vec1(...);
    foo(vec1); // fails
    
The idea is that you should be allowed to pass non-const vector to const function who accepts same vector (const or not const) with const variables. Because the function foo is like saying "give me vector, I will not modify it's elements", and with current C++ standard this is not allowed.
In that case, the question should be, why am I attempting to convert one concrete type to another concrete type?

If you're writing a program, you should use the same type, std::vector<char* >, everywhere.

If you're writing a library, the API should avoid including container details in function parameters, and const and non-const T should be allowed.

    template<typename Container>
    void foo1(Container const& c);

    template<typename Iterator>
    void foo2(Iterator first);

    template<typename Iterator>
    void foo3(Iterator first, Iterator last);

    template<typename Iterator>
    void foo4(Iterator first, std::size_t num);

    template<typename T>
    void foo5(std::vector<T> const& vec);

    void foo6(char const* const* first, std::size_t num);
foo6 is a pretty good alternative here, imo:

    std::vector<char*> vec(...);
    foo6(&vec.front(), vec.size());
It would be cool if the compiler could figure templated type conversion out, but the crux of the issue is, as I understand it, that T<A> and T<A const> are not necessarily implemented the same way.

Also note that std::vector<std::string const> won't compile -- it wouldn't be copy-assignable -- so these issues mostly seem to arise specifically when dealing with C strings and/or C compatibility. And reinterpret_cast is amazingly helpful for porting from C.

Even if you ignore the way that the types of template instantiations are (for good or for ill) unrelated, these two types are not compatible. Say this particular conversion were permitted. You have your function. (String literals are const char * .)

    void blah(vector<const char * > &xs) {
        xs.push_back("blah");
    }
And you have the code calling it:

    vector<char * > xs;
    blah(xs);
And that would not be valid. The rationale for the conversion rules for pointers to pointers is based on a similar sort of problem. (In fact I think it's exactly the same problem, at any level, but that only just occurred to me, so perhaps not.)

(This isn't to say there aren't other similar sorts of conversion that would be safe, and that the language perhaps should support, just that this isn't one of the valid ones.)

But that's exactly what is const is created for — preventing you from doing that. Why would you want to break the safeguards somebody has deliberately put in place?
There's also two places you can put "int" in a function declaration, but nobody ever seems to complain about that ;)

I'm not even sure I understand the rant, though I've been a fan of const for years so it's probably automatic by now. So, say you have a class with a const member, and you have to pass it in to a function? Well, that's a bit unusual - const members are pretty rare in my experience. But the underlying problem sounds like: you have a const object, and you want to pass it into a function. There are three possibilities, I suppose:

1. The function takes const T & or const T * , because it doesn't change that argument. So no problem.

2. The function takes T, because it doesn't change that argument (and the object is small and/or the programmer doesn't care about the copying - irrelevant issues here). So no problem.

3. The function takes T & or T * , because it changes that argument. Compilation fails! But - no problem! Because this is what you want. You passed what's supposedly a const object into a function that expected to be able to change it. Obviously compilation has to fail.

So maybe the problem is people declaring parameters as T & or T * , when they meant const T & or const T * ?

I bet if C++ had const by default, this problem would never arise. We'd be striding, right now, arm in arm, towards our glorious const-filled destiny, singing a song about it as we went.

As I recall isn't there also "const T const &"?
No, but you can have that with pointers, since the constness of the pointer itself (i.e., whether you can change the address) is separate from the object it points to (i.e., whether it might point into ROM or not). So you can have T * (variable RAM address), T * const (fixed RAM address), const T * (variable ROM/RAM address), and const T * const (fixed ROM/RAM address).

(References, by contrast, can never be reseated. So const T &const doesn't make sense. But... I didn't try this right now to double check, so if it works - though I think it doesn't - don't blame me. Or, if you do, at least allow me to plead extenuating circumstances, in the form of C++.)

That seems right, I must've swapped that behavior with that of pointers in my head.
If you're complaining about const functions, as in "int foo(void) const;," it helps to think of it as declaring that the implicit "this" pointer being passed into the function as its first argument is being cast to type "FooType const * " rather than "FooType * ." The reason it has to go at the end of the function declaration is that member functions always have an implicit first argument unless they are static. This is also why you can't declare free functions as const functions. They don't have a "this" pointer with associated fields to manipulate.
I don't really understand what you're saying.

'const' in C and C++ is broken. Not only is it like a Chinese word that varies wildly in meaning depending on where you use it and how it is inflected, but in C-family languages, 'const' modifies type, making objects that benefit from the compiler hints 'const' implies type-incompatible with objects that do not.

They're not type-incompatible in any way that doesn't violate those compiler hints in the first place - C and C++ fully support sensible coercion between const and non-const types. What more do you want?

This results in the problem of some know-it-all deciding that a core API needs to be const-correct, and checks in changes making it so, only to find that the entire fucking code base is now broken

Would you rather it compiled and silently broke? If some dingus breaks the build by changing an API without checking in the corresponding code using the API, how is that C/C++'s fault?

By contrast, languages such as Ada have explicit and implicit constantness restrictions ('in' parameters, for instance, cannot be modified), but these do not modify the type of the object, allowing objects with these restrictions to be type-compatible with objects without them.

This is bizarre. Can you take that 'in' parameter and then pass it on to another function as an 'in/out' parameter? If so, then either

1. Ada just made you a copy silently (bad)

2. Ada is broken and 'in' means nothing (worse).

If neither of those are true and an 'in' can't be transitively passed on as an 'in/out', then that's a type - however you want to refer to it, 'in' is then a type with all of the 'broken' type restrictions you're railing against in C/C++.

const is type-incompatible like this:

Suppose you want to write a function that returns all the nodes in a tree that satisfy some property. In C++ you have to define two different versions (or use templates to make the compiler clone it for you):

  vector<Node*> GetGoodNodes(Node* root);
  vector<const Node*> GetGoodNodes(const Node* root);
If more than one type is involved in the operation, there can be a combinatorial explosion.
I don't feel that I understand purpose of this function yet.

Does this function return data point that it creates itself, or does it retrieve these nodes from somewhere else? If it's the first option, who's in charge of deleting them? If it's a second option, who's in charge of counting references to these objects? Also, if it's a second option, and this data points are retrieved from a certain storage, are you absolutely sure that whoever gets this data should be able to modify them?

> Does this function return data point that it creates itself, or does it retrieve these nodes from somewhere else?

It returns pointers to the nodes in the tree. You know this because the caller isn't supposed to (or allowed to) delete them, because if the caller was responsible for that, they'd be wrapped in smart pointers.

> If it's a second option, who's in charge of counting references to these objects?

The pointers in the return value are valid as long as their particular descendant of the function parameter isn't deleted. There's no need for reference counts, and if they're present at all, they aren't updated by this function, since the caller isn't responsible for decrementing them. If the caller was responsible, the return value would be a vector of smart pointers.

> Also, if it's a second option, and this data points are retrieved from a certain storage, are you absolutely sure that whoever gets this data should be able to modify them?

If they have a const node *, they shouldn't. If they don't, they should.

Thanks! Your first two answers would be obvious if we assume that we're working with modern codebase written by adequate developers, but that's a very strong assumption to make, so I wanted to be specific.

And your final answer is, well, exactly the point I was trying to steer the conversation to. In other words, if you declare both methods, it means that you're doing something wrong: you're giving away data mutably and immutably at the same time, and it just doesn't make sense.

You aren't.

If you have a non-const node, you can access its children non-constly _or_ constly (which you could do anyway, since you could make your reference to the node be const at any time). If you have a const node, you can only access its children constly.

This makes perfect sense.

My bad: didn't read the code carefully, thought that these were methods.
> if we assume that we're working with modern codebase written by adequate developers

Yeah, come to think of it if there's a chance this function came from a pre-C++11 codebase I wouldn't be so sure that the caller wasn't supposed to delete those nodes. Well, it'd be an odd thing for this particular function, I guess, but it's something I've seen or might have done, in general. In that case maybe I'd have had the function take an output parameter instead, in order to give it a scary variable name.

Yes, and what's wrong with that? You certainly don't want someone from the outside altering the nodes directly if you have an API which should be used instead.

Whenever I need to return a non-const reference/pointer to some inner data (which is not often) I name the method "mutableFoo()" to make clear what you're getting.

But most of the time (provided a sane API design) you won't have that problem anyway.

First of all, Ada may have already made a copy of the value; small (register-sized) values tend to be passed by copy into subprograms.

If 'in' is a type than so is the concept of an lvalue in C and C++ -- because constants (and 'in' parameters which function as constants with local scope) in Ada are not lvalues; they cannot be assigned to by the semantics of the language. (In C and C++, every sense of 'const' can be gotten around; even const methods can mutate object instance variables by const_casting this.) You can call any constraint imposed by the language a type and that may be true in the abstract sense, but what counts when talking about types in a language is what the language's own type system has to say on the matter.

Parameter modes (in, out, in out) form a part of the type of the subprogram (procedure or function) the parameter is a part of, but constantness is not a part of the type of the value in Ada. Note that this is not the only way types differ in Ada than in C++ when it comes to access: C++ types encode information about how a parameter is passed, Ada types do not. The Ada declaration:

    procedure Foo(I : in Integer);
may be equivalent to C++

    void foo(int i);
or

    void foo(const int& i);
depending on how the compiler chooses to pass the values. Note that even 'in out' parameters may be passed by value through a 'pass by copy-in copy-out' mechanism, so whether a parameter is passed by value or reference is largely handled behind the scenes, so the type system doesn't include that information. If it did, Ada would be even more verbose and unwieldy than its reputation suggests, as type enforcement is much more strict in Ada.
You can call any constraint imposed by the language a type and that may be true in the abstract sense, but what counts when talking about types in a language is what the language's own type system has to say on the matter

What counts isn't so much what the specification calls a 'type' but rather how the compiler does type reduction - and with all of the compilers I've worked with, argument decorators like 'in' & 'out' are typically handled during type reduction.

depending on how the compiler chooses to pass the values. Note that even 'in out' parameters may be passed by value through a 'pass by copy-in copy-out' mechanism, so whether a parameter is passed by value or reference is largely handled behind the scenes, so the type system doesn't include that information. If it did, Ada would be even more verbose and unwieldy than its reputation suggests, as type enforcement is much more strict in Ada.

Very interesting! I know very little about Ada - other than that it has generally been considered as a safer alternative to C for applications-programming in the aerospace software world.

At the same time, I can say that without the ability to determine the how of how the compiler will pass arguments - by value, by copy, by reverse copy, by reference - I wouldn't consider Ada to be an alternative to C in the systems-programming domain, any more than I would consider Haskell or Javascript to be systems-programming languages. Your original claim, in your words, was that 'const' in C and C++ is broken. C, or any other systems-programming language, simply has more constraints on what const could possibly be. The Ada approach to handling const would simply never work in C with C's implementation guarantees. To pseudo-quote a great man, Dennis Ritchie,

If you want magical argument passing, sometimes resulting in silent and unexpected argument copying, you know where to get it.

> but in C-family languages, 'const' modifies type, making objects that benefit from the compiler hints 'const' implies type-incompatible with objects that do not.

It was fixed years ago. Now const behaves properly in modern C compilers.

Dude you are clueless. I hope you aren't in the position of making technical decisions for any major C/C++ projects.
What people like him don't get is that const is not only about security. It also documents the intents behind the code and thus makes writing new code around it easier. Const really helped me thinking about better designs when I started coding in C++.
What about final for Java function parameters? A professor was requiring that and I'm not sure whether its something I should continue doing or not.
Make everything you can as immutable as possible. The less possibilities exist for data to change, the more you know about it during runtime, the easier it is to reason about it. I love the trend that new languages, like Swift and Rust, make it really easy to make variables immutable and even disallow using "null" values unless a variable is explicitly nullable.
To provide a counterpoint, and I say this as a big casual user of Haskell and Rust (both immutable by default), but a professional Java developer.

I work on a large, mainly Java codebase. If we used `final` everywhere it is applicable, the code would have a ton of visual noise. We find that `final` is not as valuable in most cases.

`final` doesn't buy you as much in Java as `const` does in C, or (the lack of) `mut` in Rust.

In Rust, I can pass in an object reference without mut, and I know that the object will be the exact same after the function call.

In Java, even if a function takes `final ArrayList<..> xs`, the function can still delete every element of your array, modify elements at will, etc.

That means `final` is basically useless as far as using an API goes (I don't care if the implementation of a function reassigns to the same variable as the object I'm passing in, but I do care if they mutate it).

`final` only helps you avoid dumb reassignment bugs that tests should probably catch anyway, and in that case, if you are already writing good tests, why pollute the code with the visual noise of `final`?

Small nit: you can know it's the same, unless it's a type which offers interior mutability.
Which, naturally, you should be avoiding, too, to ensure immutability and thus consistency and predictability across the entire piece of code. =)

(Obviously you know that, Steve, but it's the sort of thing that I find a lot of Java folks mentally don't get.)

On the contrary, it buys you much more. The final keyword in Java will result in compilation errors if you fail to assign it a value for all possible branches within its scope. And it's 5 characters to prevent a whole class of errors for free (erroneous assignments to method parameters), so why not do it?

As for "visual noise," I find it helps to highlight variable declarations and results in more readable code, but we're firmly in the personal opinion area here.

For where we do use it:

* Member variables of a class that should be initialized in the constructor

* Static final constants

* Any configuration-like variable

* Like you mentioned, when you need to initialize a variable in a particular scope, but the initialization could happen in several control paths of inner scopes

And coming full circle with the original question, I'd add:

* Function parameters.

Re-assigning a variable used as a function parameter is frequently a mistake, and almost always makes code more confusing. I find the "this is defined only once in this function" philosophy to be useful in keeping complexity down in Java programs. Even if final doesn't make objects immutable.

> `final` doesn't buy you as much in Java as `const` does in C, or (the lack of) `mut` in Rust.

Quite true.

> `final` only helps you avoid dumb reassignment bugs that tests should probably catch anyway ...

There is another reason for declaring parameters `final` in Java. It is the only way[1] which they can be used in an anonymous class definition such as:

  return new SomeClass () {
    override int addOne () {
      return aNamedOuterMethodParam + 1;
    }
  }
1 - "The only way" as of Java 7. Newer versions may have removed this restriction, I haven't bothered to check.
Curious. I haven't written anything in Java for a long time so I wasn't aware that you could mark parameters as `final`, or what that would mean.

If you are working with code where you know that functions never modify their parameters then it is simpler to reason about what it does. I prefer to write code this way myself if there is no language mechanism to enforce it.

Other possible uses of `final` (to tag methods or classes) have the downside of reducing the flexibility of code by removing interfaces / "seams" that can be overridden. This reduction of flexibility will generally make things harder to test, which may or may not matter. Michael Feathers has a short article discussing this [1].

[1] Michael Feathers' "Testable Java" : http://www.objectmentor.com/resources/articles/TestableJava....

> What about final for Java function parameters?

For built-ins, such as numeric types and "char" (String is obviously disallowed from this definition), final will prevent changes to instances of those types similar to what "const int" does for C++.

For pointers, however, the final keyword in Java limits the ability to change the variable holding the pointer, not to what it references. The equivalent in C++ would be:

  SomeClass * const foo = &instanceOfSomeClass;
Here, the pointer "foo" could not change, but operations changing foo would be allowed.

Java (the language) does not possess the semantics to express "the pointer given to a method cannot allow changes to what it points."

Yep, if you want an immutable list, or whatever, you have to make sure your list is immutable, which usually involves defensive copying.
const is an awkward poorly thought out keyword syntax that is too ambiguous. Const is a good idea, how it was implemented in C++ was not. One of my old managers used it as his C++ interview question to 'really see if they know C++ well'.

See http://duramecho.com/ComputerInformation/WhyHowCppConst.html

Absolutely nothing there was surprising. The worst thing is that if a library uses const, you have to use it too.
That library might have been coded assuming invariance and a mutable implementation might not have been possible with the same time/space behaviour.

If I wrote a library and made something const, I did that for a reason. I didn't do that just to piss you off.

Explain?

The most common usage of const in library code is for function parameters:

    Iterator find(T const& value) const;
The const actually _helps_ callers: find accepts both const and non-const references. A non-const argument will be implicitly cast to const by the compiler.

Compare that to:

    Iterator find(T& value) const;
This function signature accepts only non-const references (unless T is const). A caller must const_cast a const argument to use it (bad).

Return values are occasionally references:

    T& front();
    T const& front() const;
But "auto" makes the code shorter when the return type is const or unknown:

    auto& v = c.front(); // overload is deduced by the compiler based on the constness of c.
I don't think I saw anything strange or ambiguous in this article, and the only thing I didn't know before. And I'm a beginner C++ programmer.
So, to summarize the article in the link,

1. I don't like the syntax for const [fair enough]

2. I want to have an object that obeys someone's const'ing of it but still be able to mess around with its internal state (like for logging, data caching, or intermediate calculations), and there's no way of doing that...

3. ...except that there is - it's the mutable keyword, but that's bad because other programmers other than me who are using it to modify 'const'ed classes (for logging, data caching, or intermediate calculations) can't be trusted.

Seriously - that's what he says:

One in particular annoys me because my programs often needed to be optimized for speed. [because I'm 'leet] This is that a method which is declared ‘const’ cannot even make changes to the hidden parts of its object that would not make any changes that would be apparent from the outside

...

In later versions of C++, the ‘mutable’ keyword was added which enables ‘const’ to be overridden for this purpose but it totally relies on trusting the programmer to only use it for that purpose so

!!!

What happened to altdevblogaday.com anyway? It had content similar to this.
I've been wondering the same thing for a while. I don't know why it just disappeared out of nowhere.
Isn't it awful when such resources vanish?

When Megaupload was destroyed, it was like losing the Library of Alexandria to me. The ATF can't just destroy the entire nation's set of self-storage units because they found drugs or pirate DVDs in some of the units. But that's what happened with Megaupload. Some people lost family photos, some people lost backups of theses... Why couldn't the authorities have taken it over, eliminated illegal content, and turned it over to some sort of Vichy CEO? There need to be protections for data storage customers in a FDIC sort of way, I feel.

Police (and the like) are paid for capturing criminals, not for doing what is morally right (some hope they are the same thing, but many times it isn't)
It's dead. I remember Mike Acton said something like site had serious technical issues or whatever and since then it's dead.
I have a story kind of similar to the one called "...Or is it over here!?"

A friend of mine was having crashes with a program. When debugging it he found that a bunch of his local variables had weird values. He suspected that there might be a buffer overflow elsewhere that was trampling over the memory.

The fix? Just add "char buffer[ 1000 ];" to the function to absorb the damage. It fixed the crash and it shipped like that.

This reminds me of an older "dirty trick" where a buffer was sacrificed, instead of added, at the end of the project in order to ship.

See "The Programming Antihero"[1].

[1]. http://www.gamasutra.com/view/feature/132500/dirty_coding_tr...

I've done something like this on a production data base server before. Maybe not the same thing but I allocated a really big file because mysql would occasionally grow its ibdata file to full the disk before we could handle the alert. Deleting this file allowed room to maneuver after restarting the database and dealing with this run away journal file.

The other similar urban legend is the enterprise teams which have for(int i=0;i<10000000;++i); loops in code which they can remove a zero when performance boost is needed and they can quickly provide a fix.

Now this is a dirty coding trick!
There's even a compat shim in Windows for that kind of thing where the memory manager would allocate a few bytes more than requested so that subsequent code (that ran fine in Win 95, for example) could overrun the allocated buffer without crashing. Back in Vista there were around 5000 applications that had shims applied by Windows to make them run correctly. I wonder how the count would look like today ...
Ah, debugging games... It screams desperation when you see code that is sprinkled with "int 3" 'cos no one knows where or why it's crashing.
There's a whole lot of desperation in the air when you're final-ing and your development director is standing over your shoulder at 1 in the morning. :-)
The battery backup initialization hack from NBA JAM TE is random and hilarious

http://www.ign.com/cheats/games/nba-jam-tournament-edition-g...

Is there an explanation for this somewhere?
I was also looking for more info on this. Sounds like a good idea for a blog post if anyone can shed light on how/why this works.
Agreed. My limited Google searching turned up nothing.
My best guess would be some kind of anti-piracy measure failing.
A couple of those are cited like this:

> - Anonymous (sourced from Reddit replies to the original 2009 Dirty Coding Tricks article)

So not anonymous at all then. reddit comments have usernames attached to them, URLs that can be linked to, and even an on-site messaging system that can can be used to ask the author for permission to use the content. Heck, every comment has an "embed" link below it to conveniently embed the properly cited comment right on your page.

Is this a thing that's okay to do? Take someone else's content from someone else's website, copy-paste it into your article, and claim it was "anonymous"?

Would this author be okay with it if I copy-pasted their articles to my blog? What about if I stole all of the comments posted to their articles to make my site look more active?

No, it's not okay. The media, especially gaming publications, have been doing this stuff for years now, and it's ridiculous. Some publications have wised up, but many haven't.

It's greatly amusing when someone just gives up all pretense and just scrapes a subreddit, then SEO blog spams every single post - because then the members will upvote stories about how terrible the website is. I unfortunately can't find anything specific at the moment, but 2 of the big ones I remember was /r/makeupaddiction and /r/gaming.

EDIT: For the curious, here's the mod post about the /r/makeupaddiction incident https://www.reddit.com/r/MakeupAddiction/comments/39o74y/mod... I'm unable to find the others at the moment, though there is a list under the top comment on the thread I've linked.

Something something something ethics in games journalism!!!

(Oh, hang on, male sounding name - as you were...)

"According to a reddit comment, which we've stripped the username from" is quite silly regardless the genre of your article.

There's nothing wrong with being accurate - in this case, it provides users with a way to follow up on the item in the story.

But maybe the article writer asked, and the user preferred not to be named, for all we know.

Depending on which bit of Reddit, its also entirely possible the only way of reporting that "non-anonymously" might have been to say "According to a Reddit comment by BigDick4YoMama", which quite likely isn't what your editor wants to see in your articles. (But you are right, and I deserve the downvotes I'm getting here - it was a pretty poor attempt at humour…)
Just to be fair the original reddit entry [0] no longer has that comment in it (it was probably deleted) so maybe they just went with "anonymous" after being unable to find the actual source.

[0]http://www.reddit.com/comments/9ch0s/dirty_coding_tricks_nin...

There are two cited that way, and neither appears in that link. I don't think both were coincidentally deleted, I think that's just the wrong comments page

Besides, he has to have fetched them at some point and he should have taken the cites at the same time. "I found it somewhere on reddit" just isn't enough. It makes me wonder where he stole the other ones labelled "anonymous"

> we'd inexplicably get a crash in printf [..] The client in debug would print out the hashes of every content package the server told it to load, and apparently one of them (on this build) had a % in the hash. We couldn't figure out a reasonable fix for it, but #ifndef PS3 worked just fine until the next data build

Friends don't let friends printf(str).

I didn't really understand that problem. They couldn't fix this?? Like, they didn't know how to escape/replace percent signs or print differently? Maybe I am missing something but it does not look like a particularly elusive problem.
Yeah I thought that one was weird too. Also I wouldn't really call it much of a dirty coding trick if it was just something that was hacked in during development! Many times I've #ifndef <someplatform> because something or other didn't work on that platform. Then later before shipping you fix/implement it!
How I understand is that they had printf(x) somewhere and some values of x included the '%' character. If this has been inside the UE and the x itself was a hash value then both replacing with printf("%s",x) and changing the x's value could be problematic.
> Here is a horror story from the good old days when men were men and used DirectX 7.

Ugh.

> Personally, I hate CONST with a passion, so I like this trick.

Ugh.

> PhysicalObjects could take damage. The air strikes did enough damage in a large enough radius that they were quite literally "killing" the camera. I did fix the bug by ensuring that cameras couldn't take damage, but just to be sure, I boosted their armor and hit points to ridiculous levels. I believe I can safely say we had the toughest camera in any game.

Awesome.

Regarding the camera with hitpoints, is there a name for that class of bug? Poorly thought out code reuse? Overly specific inheritance?

A similar seeming bug is the old "kangaroos with rocket launchers" story (from military simulations, not games) [1].

[1] http://www.petting-zoo.net/~deadbeef/archive/4488.html

It's inherent to common game architecture. Far out the most flexible way of dealing with the multitude of complex entities in a game is to not work with inheritance but rather with 'components'. Ideally this means that an entity is nothing more than a UUID for which data is stored in component tables (a la relational databases).

Unfortunately that approach is rather cumbersome to reason about and brings with it unhandy syntax requisites. Given an entity UUID, how do you get a value for some property? It would be component_table_get(health_components, entity_id)->hitpoints. Or something similar. (note: what happens if you accidentily call that function on a entity_id for which no health_components entry exists?)

The alternative which is really fine for smaller games and which often leaks into the codebase of larger games, sometimes for performance reasons is to make the entity a struct which has some members common to all entities. Now you can do entity->hitpoints, but the downside is that every entity, including abstract game components such as the camera also have hitpoints.

If you're curious why games don't do inheritance (anymore) look up articles about Component Entity Systems, they usually do a good idea of explaining why games are too complex for inheritance.

> Unfortunately that approach is rather cumbersome to reason about and brings with it unhandy syntax requisites. Given an entity UUID, how do you get a value for some property? It would be component_table_get(health_components, entity_id)->hitpoints. Or something similar. (note: what happens if you accidentily call that function on a entity_id for which no health_components entry exists?)

I work with Unity engine (which uses exactly that model), and in good code these problems don't arise — or, rather, these checks are meaningful and actually represent the logic, rather then being "unhandy syntax requisite".

Imagine that you have a lava object with a trigger collider (that means that it doesn't influence the physics) and a Lava custom component (MonoBehaviour) on it. In `OnTriggerEnter` method of Lava you run `var health = GetComponent<Health>()` method on GameObject that entered lava and determine if that thing is something that can be damaged — because, quite possibly, it is a camera (as in that example) and the method will return null. And then, if it is something that you can damage, then you can use the `health.Damage(5 /* random dice roll */)` on it.

I can't recall the source, but the story goes as follow.

In some game, menu was written on stone tablets. Due to the bug tablets received guard AI and would randomly walk away to patrol the island.

There used to be a bug in Kerbal Space Program where solar panels would be occluded by the UI windows.
That's what you get when you keep your UI and game objects mixed together in a some sort of "scene". I suppose Unity that encourages this style.
Actually, KSP uses the old UI framework, where UI objects are "created" every frame. But in new UI framework UI objects are indeed mixed up with game objects, and it makes perfect sense: they live in the same space. Game objects can be 2d, and UI objects can be 3d. For example, you can easily implement weapon UI as a physical display on your weapon's back. You can change your menu from being 2d overlay to be floating in space and collide with level walls in 2 minutes.
> > Personally, I hate CONST with a passion, so I like this trick.

> Ugh.

Gamedevs gonna gamedev.

I've read that Wing Commander anecdote before, and it still doesn't make any sense to me (also I don't remember that original message "Thank you for playing Wing Commander" message and every abandonware version I found had a different message - "You step out of the airlock and into.."). It doesn't make sense because EMM386 is the expanded memory manager that came with DOS. It's not something you ship with your game and can hex edit at will. Now if it was a 3rd party library that USED EMM386, and which they didn't have the source for, then that might make sense..
In the DOS days the operating system was mostly just a boot loader and a set of tools. Whichever program happened to be running at any given time would have complete control over the system. So a program could simply find out where any other program was in memory and modify it, which for something like changing a string was fairly easy.
Yeah sure, I know, so I suppose they could have modified the string in memory. But he specifically says that he "hex edited the error in the memory manager itself", which makes it sound like he modified an executable. A programmer wouldn't say he hex edited a string in memory when what he meant was he wrote some code to replace the string in memory.
Maybe DOS allowed one to to statically link OS-provided libraries? I have no clue, this was way before my time.
There were no OS-provided libraries, only a documented list of software interrupt calls you could use! Ah the old days..
I assume that part of the story was mangled in the telling/re-telling.
There were third party memory managers that you could use in DOS; for example, QEMM and 386max. I assume Wing Commander was licensing and shipping one of those rather than relying on the stock memory manager. In fact in 1993 MS licensed some technology for later versions of EMM386 from Helix's third party memory manager[0].

[0] https://en.wikipedia.org/wiki/Helix_Software_Company

Yeah I used to run QEMM. I don't think anyone would have shipped QEMM or 386max with their game, since they were commercial products for end users. It sounds like, as someone else said, the story was mangled over time.
EMM386 only became the defacto standard for games around 1993 or so. Prior to that developers would purchase or create a solution from scratch to deal with the rapidly shifting PC development environment. A decent chunk of the market was still on 286, and this was the most likely target for the first Wing Commander (1990) - later games from Origin such as Ultima 7 and Privateer continued using memory extenders branded "Voodoo" and "JEMM" that were known to run in unreal mode[0] - they were generally a nightmare for users as they were less stable than EMM386 and typically had a huge conventional memory minimum requirement, but it was tolerated as what one had to go through to play high end PC games.

[0] http://wiki.ultimacodex.com/wiki/Voodoo_Memory_Manager

Right, yeah that makes sense then. Since WC also ran on a 286, they must have created or licensed an EMS library.
I wonder if these anecdotes would be a good litmus test for developers. They make me cringe, but I work on business software, not games.

I really don't like the idea of papering over the bugs so that your testers can't find them anymore, I'd much rather find the underlying issue. On the other hand, the described changes were often very practical, solved a customer need, and were manageable to implement. So that sounds like a win!

Few things contribute to it. Mostly it's lack of time, and the fact that we don't really have to support code for long periods of time. If the input code works then it works, when a game is released its code it's mothballed on a server and I don't even see it again unless there's some urgent patches(and 6 months after release the chance of that happening reduces to zero), and then I have to request IT to give me access to that code again.
AUCTION..... AUCTION........ AUCTION.......The Nigeria Custom Auctions Is Up Again and Granting Nigerians the Privilege to Own Vehicles at Affordable Rates. Approved By The Federal Government Of Nigeria, All Individuals Should Note That These Vehicles Are Impounded Due To Smuggling And Improper Importation Which Has Resulted In The Forfeiture Of The Said Property As Penalty For The Illegal Act. Consequently, These Impounded Vehicles Are Now Being Auctioned To Eligible Nigerians In The Ongoing 2014/2015 ( N.C.S. Batch B-) Vehicle Auctions And This Action Is In Line With The Directives Of The Government Of The Federal Republic Of Nigeria. These Vehicles are neat, in a perfect condition and Has Never Been Used In Nigeria. The Vehicles Are Currently In The Custom Warehouse At Ogun State, Idiroko Border Ports Awaiting Removal By Clearance.. Contact Address: Operation 2-Enforcement Office, Idiroko BordeCommand. Contact MRS OLORUNDA GLORY ON 08068017569Name:zonal commander Public Relation

Officer, Federal operations Unit, investigation and inspectorate. Contact MRS olorunda glory 08067834923Office Mailing Address: Nigeriacustom916@gmail.com THIS CARS AND SUVS ARE VEHICLES RANGING FROM 2001 MODEL TO 2013 Prices of some Toyota

cars: Land Cruiser-N700,000 • Toyota Prado N900,000 • Toyota Corolla –N500,000 •Toyota 4Runner-N850,000• Toyota Tundra-N700,000• Toyota Tacoma-N750,000•

Toyota Camry Tiny-Light –N350,000• Toyota Camry Spider-N800,000 • Toyota Camry Muscle-N700,000• Toyota Avensis – N200,000-N500,000 • Toyota Yaris – N300,000 • Toyota Matrix – N400,000 • Toyota Camry Big Dady-N 450,000•

Toyota RAV4 SUV –N600,000 • Toyota Hilus -N750,000 • Toyota Dyna Truck – N350,000 • Toyota Hiace Bus – N600,000 •

Toyota Coaster Bus 32 seaters – N600,000 . Toyota highlander- N800,000• Toyota Sequoria-N500,000 • Toyoya sienna -- N550,000 • Toyota Avalon

-- N500,000 • Toyota Venza --N750,000

Prices of some Peugeot Cars Peugeot c230 N300,000 C300 N450,000 Peugeot-406 N500,000 prices of some Honda cars Honda Civic cars – N350,000. Honda CRV 400,000-750,000. Honda EOD 600,000. Honda DC 700,000. Honda Evil Spirit 800,000. NOTE=The nigeria custom service Recruitment and Replacement of new take is on for BATCH 1 hurry up For more enquiry call MRS OLORUNDA GLORY ON 08067834923 Thank for your patronage.

> I then remembered that when you put the window in the notification area or in the start-menu bar, Windows immediately reclaims unused/freed memory.

Wow. Is this a horrible hack or a wonder of the tight integration between the GUI and the kernel in an operating system designed to be used in a desktop? I'm torn :)

I think that this is some kind of oversimplification of what actually happened.

AFAIK there is not even an operation like "put window into notification area" as part of WinAPI as the icons are mostly orthogonal to windows (and are not even intended to represent "more-minimized" windows).

The icon has to reference some window, but only because it generates window messages that have to be consumed somewhere. Fun fact: at least on 2k and XP, when the window goes away, the icon stays visible unless it is explicitly deleted by user code and is removed only when some message would be sent to now non-existent window (ie. when users mouses over the icon).