tags:

views:

4828

answers:

58

In 1986 or so, Bjarne Stroustrup famously said: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off."

What is, in your opinion, the most spectacular way to blow your leg off in C++? Points for originality, and for helpfulness.

+14  A: 

Here on SO, Joel Coehoorn wrote about this example:

  if ( blah(), 5) {
   //do something
  }

"Note that the , operator could be overloaded for the return type of the blah() function (which wasn't specified), making the result non-obvious."

TonJ
IMO using a comma in an expression like this is usually non-obvious anyways.
Greg Rogers
Um, yeah. Nice to be singled out :)
Joel Coehoorn
If comma can be overriden to deliver unpredictable results, doesn't that make "if( bla() + 5 )" just as problematic?
Bill K
Steve Jessop
@onebyone: I hadn't thought of disabling the short-circuiting. That's really really sneaky!
TonJ
@Bill K: the difference is everybody knows you can override the + operator, but fewer people know you can do that to the comma operator too. I didn't know.
TonJ
A: 

By using C++.

Sorry, used it a lot, but this is the worst language ever. If you really really have to be low level, use C. If not, use a real OO language (one with Garbage Collection, C#, Java) or a dynamic language if you are higher level than that.

The only language I can name right now that I would not choose for any purpose is C++


Edit:

Programming in C++ it's virtually impossible to think in OO because you have to track GC. I've virtually never seen good OO c++ code. (It's also somewhat annoying to create new classes because of header files, so most C++ classes seem to be longer and manage more than one concern, another bad OO concept).

I've used C++ and still use it occasionally, but not for OO code, and would never choose it for a new project where the language wasn't set already. I've worked two embedded systems where Java did most of the work including a spectrum analyzer (pretty much an o-scope) where even the trace was drawn in Java.

My point was, C++ doesn't really offer any advantages (It's about twice as fast for the CPU usage, I can't recall the last time I was near 50% cpu usage on one app for more than a second), and has so many ways to shoot yourself in the foot that it's not even funny.

Actually there is another advantage--C++ is the last really hard language and it keeps the barrier to entrance higher. I don't know a lot of C++ programmers who don't understand the language, and many are excellent programmers--so (as opposed to Java, C++, VB and Ruby) C++ apps tend to be a bit more consistently good.

Bill K
Doooown the toliet you go.
Vicent Marti
Maybe you should suggest that they implement a badge for getting a lot of downvotes.
Kip
@Kip, I agree with you there. It would be something like "Blasphemy" for 20 or more down votes. :)
epochwolf
That browser you posted this from... try writing one of those in C# or Java.
Vulcan Eager
Thanks for stirring up the controversy. I love C++, with all its faults.
TonJ
Anti-C++ respect. Agreement with bill-k here.
ephemient
@epochwolf: "Douchebag" for 50 or more downvotes. :)
Kip
I downvoted this too, not because I disagree one iota, but because it seems to be contrary to the spirit of SO and not an answer to the question... my single downvote decremented it from -14 to -18, so there must be some system in place!
Grank
@Kip, can't argue too much with that.
epochwolf
@Grank, I don't like C++ that much either but this answer is totally out of line in my opinion.
epochwolf
This post is a great way to earn rep, because it will be alternately upvoted/downvoted (you only need 1 in 5 to upvote it and fewer that 5 'offensive' tags.)
finnw
Hasn't worked all that well for Bill K -- at the moment, he's earned 60 points from it, and has had 52 of them taken away by down-votes. :-)
Head Geek
This is the most spectacular way to shoot yourself in the foot with a comment.
Ates Goral
This question doesn't qualify as "helpful."
Robert S.
he got voted down because he made a broad generalized bias comment about C++ as if he spoke for everyone. It did not answer the question but more or else shot down anyone using C++. The tone he uses borderlines "you must be stupid to use C++"
radioactive21
Sorry, didn't mean it as an insult to any person, as I said C++ programmers are usually some of the better ones, and sometimes you don't have an option. That said, I really can't figure out any reason to start a new project in C++ over C and/or Java/C# depending on your task.
Bill K
Being, as I am, a C++ lover (and Java dismisser :P) I just couldn't resist joining the downvoting fest :D This is indeed a great example of how to shoot yourself in the foot!! There needs to be a new badge on SO: "Heretic" or the like, for posting an answer valued less than -10!!
Joe Pineda
@BillK: your comments show you don't really grok C++. Don't need garbage collection if you use RAII. Create new classes because of header files? WTF! Something I hate from Java is its insistence on one class==one file! "Never seen good OO C++ code" and "apps a bit better" - flagrant contradiction?
Joe Pineda
Joe: The fact that C++ code might not be good OO doesn't mean it's not good procedural code and the comment about classes/header files is that I have to edit two files (header and C) to create a class, making class creation more painful. ps in java I can and often do have many classes in one file.
Bill K
The fact that C++ code uses 50% less cycles than Java for the same work may not be so important for your desk PC, it is very important for server farms. If you need 50% less servers to serve the same number of clients, that is a big deal.
TonJ
@TonJ Except for a few very specific cases, most server farms I've seen or heard of are not in C++. Since your example is correct, it seems to be evidence that many companies are willing to pay that price not to have to use C++. Good point, thanks. I wasn't expecting support at this point.
Bill K
A very entertaining conversation. Have you considered this one: C++ could help save the planet because if used correctly it can use less clock cycles than Java etc. This results in less energy burnt and less nasty emissions.
Scott Langham
@Scott I'm kind of wondering how it even went down that road. I never said there was a problem with C, and C is still faster than C++. You can even code C++ as C, that's fine too. but OO without GC is just a silly concept.
Bill K
And by the way: http://www.idiom.com/~zilla/Computer/javaCbenchmark.html
Bill K
My opinion is exactly the inverse of Bill K, I wouldn't do anything serious in a another language. If you want to make sure that your app will still compile and work in 10 years, use C++. Very powerful language by the way (if you know how to use it properly).
Martin Cote
ahahaha, -39 neat! well i've got the exact opposite opinion too :)
Johannes Schaub - litb
Yeah, this is one of my favorite posts. It really surprises me how many people defend this language. On the other hand--When I used it it had JUST come out and there was absolutely no memory management, smart pointers or anything that could make it remotely usable. I understand it got a little better, although the boilerplate/syntax ratio (how much boilerplate/non-business related complexity you have to use over the simplicity of the syntax) is still the worst of any language I've seen.
Bill K
@Bill K: I can tell you've never worked in COBOL.
David Thornley
@david thornley Took a class in it. I didn't notice much more boilerplate in COBOL than any of the other biggies of the time, just that the business logic was more verbose, but that was REALLY long ago. This is still my favorite answer discussion by the way.
Bill K
@[Bill K] respect for keeping this answer up, and +1. I doubt even a person with 27 years of C++ experience could convince the downvoters that the language sucks by any modern standard, with the single exception of wide OS support. My theory is that the "converts" are those who actually properly grok a more modern language, rather than "had a quick look and didn't like" it.
romkyns
@Bill K, C++ from the dark ages is not the same as C++ now.
Brendan Long
@Brendan Long I'm using C++ right now. It's worse than I remember. Mostly it's not the language, it's the programmers and the way they choose to use it. I've yet to see a C++ programmer who can think in OO unless he learned it in another language. Some of the flaky hacks that they use to make the code even slightly tolerable are just horrific examples of things you might invent if you wanted to allow a descent programmer to become terrible--macros--OMG.
Bill K
@Bill K, It seems like the people who have a problem with C++ actually have a problem with C (and people who still treat C++ like C). If you treat C++ like a Java with less arbitrary rules (required gc, required classes, etc), it becomes very nice to use. Also, using C++ without boost is just depressing.
Brendan Long
@Brendan Long I actually enjoy C. C++ adds horrible method signatures, breaks classes across files, puts partial implementations into the declaration (header file) and offers you no guaranteed level of support (Can I port to this platform that doesn't support GC--Hmm, complete rewrite today! (I'm working embedded so our code actually has some smart C++ programmer's reference counting implementation--does it work? Yeah! But we're embedded so if you use OO/Ref counting you'll soon trash your heap. All stuff you never have to think about with Java.
Bill K
@Bill K, I don't see how your C++ situation is any worse than using C. No built-in garbage collection, but you still have the massive advantages of: templates, the stl, boost, classes. If any of those features don't work on your platform, then you still have the rest (and at the very worst, you have C with better type checking). And how is Java better? Most likely, it doesn't work on your platform at all, and if it does, it doesn't give you the kind of control over memory that you need in an embedded application. Also, doesn't C use header files as well?
Brendan Long
Actually the code doesn't use any of those--it's cable set-top boxes--small footprint and all. What it does have is cryptic macros hiding implementation and a lot of stuff going on under the covers that I could have identified if it were C. I've come to accept that the best languages are the ones with minimal syntax, remove operator overloading, remove anything that can hide the intent of your code. Not that you HAVE to program poorly if you have those things, just that you WILL HAVE to work on bad code using those things (at least I will, if you don't, you're lucky)
Bill K
@Brendan Long The advantage of C is that nobody WOULD try to write anything large in it any more. It's a great "Portable Assembly Language" which is exactly what it was made for and is still good for quick, hand-coded routines. C++ is a monstrous mess layered on top of that that people feel is appropriate for large code bases not realizing that maintainability is 90% more important than making the code run. You can make something work in any language--but making it maintainable takes effort, and restricting choices helps for the large percentage of programmers that just don't get it.
Bill K
+9  A: 

Overriding ::new() operator. You might have grand hopes of tracking memory leaks or logging fragmentation or whatever. It almost always turns south quickly.

Jeff Mc
+25  A: 

Overloading of operators in general, but particularly new, new[], delete, delete[], and [].

Kip
don't forget overloading new[] and delete[]
workmad3
thanks, i'll add those too
Kip
sidenote: my company has list types that overload [] so that they start at 1 instead of 0. they were written long ago by fortran gurus, and now they are pervasive in our code. gets really annoying when you have to juggle base-0 arrays and base-1 lists in the same code!
Kip
What is the problem with overloading new/delete?
leod
Kip, that 1-based [] overload sounds like a candidate for thedailywtf.com :)
Jim Buck
Kip, that 1-based[] overload is just hilarious, but I have to admit, its pretty creative.
Jose Vega
This is so commonly done (and very effectively) in games. Memory management is a huge issue in game programming.
Torlack
oh. And don't forget about 'placement new'
Orion Edwards
overloading new and delete is a very valid thing to do, and hardly a problem. You can get a massive performance improvement using multiple fixed block size heaps. You can kill yourself this way, but generally you know you've done it immediately so your users don't get hurt. :)
gbjbaanb
This is like saying 'Driving a car is dangerous so don't drive a car'. Of course if done wrong it can get pretty bad but when done right it's quite useful and indeed a valid thing to do.
Andreas Magnusson
there is nothing wrong with overloading operators...
Johannes Schaub - litb
-1, overloading operators is a valid feature, and overloading new and delete is done a lot in embedded systems.
Edan Maor
+13  A: 

It doesn't happen often, but I always find this hard to track down.

if (number = 5) {
    // code
}
Rontologist
Turn up your compiler's warning level. It will catch it for you.
Ferruccio
Many compilers warn about his, which can help. I am personally a fan of the sometimes maligned construction `if (0 == callThatCanFail()){...}` despite the rough way it reads
dmckee
That happens to me a lot when switching back and forth from VB.
Ed Swangren
It's been a while, but can't you also do this in C?
harpo
This is not C++-specific.
Andreas Magnusson
@Andreas: But it _is_ a valid way to shoot yourself in the foot with C++ =]
mdec
@dmckee Another partial solution that complete your construction is to declare as much as possible all variables as const. In the case "number" was const, the code would not have compiled. This is why I only "malign" the "0 == number" idiom if the coder otherwise forget to use const where appliable
paercebal
The question implies that ways that you can shoot yourself in the foot that apply to both C and C++ are not valid answers, even if spectacular.
Max Howell
@mxcl - That is not how I read the question. To me it is asking for all ways to shoot oneself. This includes all valid C answers.
Rontologist
+37  A: 

Attempting to call a pure virtual function from a constructor or destructor. Since the derived class object has not yet been constructed (or has already been destroyed), this will result in badness. The compiler will convert virtual function calls into static calls of the base class version's of the function when it can, but there is no base class version of a pure virtual function, and undefined behavior will result. This could happen if the call is indirect, say, by calling a non-virtual function which calls the virtual function.

Adam Rosenfield
Huh? When calling a virtual function from a non-virtual function from a ctor? Why is that undefined the vtable is still that of base, am I missing something?
Motti
The C++ standard does not require that virtual functions are implemented using vtables. So in general, any consideration that says "it will probably work because of the state of the vtable" will not be describing mandatory behaviour. "Undefined behaviour" permits your compiler to make it 'work'...
Steve Jessop
*WRONG* : It's not undefined if there actually IS a base version of the function. And then it works perfectly as expected, even when called indirectly. Even if you don't use a vtable. The mechanism has to work the same: in Base::Base, calling a virtual foo will call Base::foo().
MSalters
Attempting to call a derived virtual function from the constructor OF A BASE CLASS will give you grief. Say you have Base::Base(){foo();} When you call Derived::Derived(), you'll find that Base::foo() is called, not Derived::foo(). Because when Base::Base() runs, the vtable for Derived is not up.
Stéphane
to add to @MSalters' excellent correction, only if the function is declared pure, behavior is undefined. This is defined in `10.4/6` in the C++ Standard.
Johannes Schaub - litb
+4  A: 

Relying on default parameters in virtual functions in derived classes.

workmad3
Good one - you should add an example to illustrate it though.
Richard Corden
+2  A: 

From my C++ days back in the 90s, I was always a fan of

MyType<MyOtherType<T>>

Hello right-shift !

skaffman
At least you never had to debug that (because it won't compile.)
finnw
A syntax error hardly counts as blowing the whole leg
David Pierre
If I'm not mistaken, C++0x will allow this, and compile correctly.
TonJ
It might not take off your whole leg, but it will result in a slightly embarrassing limp.
skaffman
Whether that compiles at all is actually implementation specific. Most MS VC++ compilers will error on that.
Nick
+5  A: 

Using multiple inheritance is a good way ensure that you'll have problems.

Bill the Lizard
multiple inheritance, with classes deriving from a template base class...
artificialidiot
MI's never a problem, either you have a unwieldy hierarchy .. you have ther problems than MI, or you have base classes with same-named members (and you have to disambiguate them, not too hard), or you have different-named members... and that just works. MI is only hard for compiler writers.
gbjbaanb
MI is not the problem. If there's a problem with MI, it's more likely a personality problem, i.e. someone tries to solve a problem using MI it wasn't intended to solve.
Andreas Magnusson
The diamond problem is a well-documented ambiguity that comes up a lot when using multiple inheritance.
Bill the Lizard
And therefore we have virtual inheritance, with all pros and cons.
gimpf
Diamond inheritance causes problems, and combining virtual and non-virtual inheritance can easily cause confusion. Avoid those and you should be all right.
David Thornley
+22  A: 

I've seen this a few times where someone used memset() inside the ctor to easily initialize all the class variables.

myClass::myClass()
{
   memset(this,0,sizeof (myClass));
}
Michael McCarty
lol. In my newbie C++ days I actually did that. Everyone told me that in C++ a class and a struct were identical, and I'd been memsetting structs in C for ages :-(
Orion Edwards
I've just thought - I do this for simple structs all the time... I wonder if others will see my code and think 'so that's how you do it' and apply it to classes? I'd best change that practice!
gbjbaanb
That line caused some of the code I was maintaining to perform inheritance incorrectly. It messes with the virtual pointer table which was pretty fun to debug.
dr_pepper
It's also not fully portable even for PODs: there is no guarantee that "all bytes 0" is a valid value representation for every built-in type, although of course in practice it is if only because compiler-writers would rather make it be than argue with their customers.
Steve Jessop
This is of course valid for PODs with only integral members (int, char, etc) and quite useful if your POD contains several large arrays of those types. Never ever use it in a class with virtual functions though...
Andreas Magnusson
@gbjbaanb: In C++ there really is no difference between structs and classes (except public vs private). So if you still use memset() on a struct, and someone adds a (member function, constructor, operator) to this struct; boom there goes your foot.
TonJ
I've also seen someone fix this by changing size of the allocation to 'sizeof(myClass)-sizeof(void*)' to leave room for the vptr.
Michael McCarty
+30  A: 

Needing to change the signature of a base class virtual function and disconnecting all the derived class overrides without any complaints from the compiler.

And I used to think that C#'s insistence on 'virtual', 'overrides', 'new' modifiers was being pedantic ...

Rob Walker
I get around this in staticly linked projects by changing the function signature and _temporarily_ making it abstract. Then I get different errors report for functions that implement the wrong signature then those that don't implement it at all, and I can find which ones need to be updated.
Joel Coehoorn
I agree that requiring derived classes to explicitly state they intend to override a virtual is something that should have been in the language. It also bugs me that a `static` declared in a class **cannot** have a matching `static` in the definition.
Michael Burr
Yup, I'm a multiple amputee on this one!
Dave Van den Eynde
You can only appreciate the goodness of C# and the badness of C++ if you have used both a lot.
romkyns
+5  A: 

Modify a std::map while you have an active iterator on it. I spent 3 days debugging that once.

finnw
only a problem if you delete the item pointed to by that iterator, otherwise you're fine.
gbjbaanb
A: 

You could write a firework launch system in C++ that launches fireworks automatically in time to a piece of loud classical music. Then accidentally stand in front of it with your foot in the way during the finale.

It would be spectacular.

Note (more detail as requested by TonJ): If you work on a system like this, I recommend you avoid try/catch semantics. Using a return for a firework that failed ignition is also a no-no. And, make sure any pointers are initialized to be away from any observers.

Scott Langham
shucks. the question mentioned points for originality. don't downvote me :) At least I'd recommend C++ as the best language. If I only had to use one language for everything, C++ would be it.
Scott Langham
I'll upvote you, but please add more detail, like object-oriented rockets with a Rocket Acquisition Is Ignition design pattern, or exothermal template functions.
TonJ
+27  A: 

I've initialized an array like this:

int *ip = new int(10);

Hijinks ensue when you try to use this "array" beyond index 0 (which is usually almost immediately). The problem is that the above code is the syntax to create a pointer to a new int initialized to the value 10. It only looks like the syntax for pointer to a new array of size 10.

Bill the Lizard
been there, done that, bought the T-shirt!
Martin Beckett
Oooh, took me a full minute to realize what the difference was. Good one!
David Thornley
+5  A: 

In a project that does not use namespaces, create a class named Thread with a method called run(). Then make the project use a shared library that, unbeknown to you, also has no namespaces and a class named Thread with a method named run().

No try to figure out that why when you create a thread in your code and pass a pointer to the Thread::run() method as the main body of the thread, your threads never get created.

Good times!

Hans
+5  A: 

Calling a function like this:

int result1 = f( i, i += 2 );

leads to unpredictable results. The function parameter evaluation order isn't specified in the C++ spec, so you don't know if the function will get the current value of i for the first parameter, or if it will be the value of i after i += 2 has been evaluated.

Bill the Lizard
IIRC The coma operator is very well defined. It enforces order from left to right. A better example might be "i + (i+=2)" that might give you some hassles.
Bill K
Yes, but the comma in this example is not a comma operator.
Thomas Padron-McCarthy
It might not be clear from my example, but that's a parameter list to the f() function.
Bill the Lizard
+1  A: 
int x = 7;
int y = 2;
float result = x / y;

You might think result would be 3.5, but it's 3!

Scott Langham
That's really no different than C code.
Andrew
So are a number of the other answers. It's something that's still worth pointing out to somebody trying to get to grips with C or C++.
Scott Langham
+2  A: 

If you have a a multithreaded design of any sophistication, and you feel like a few hours tracking down object lifecycle race conditions, try using raw pointers for object ownership.

Smart pointers don't make threads easy, but they certainly help.

Sam Stokes
+14  A: 

Not initializing a pointer and then using it later.

Adam Tegen
Sorry to be pedantic, but this is not specific to C++.
Max Howell
+2  A: 

Not understanding pointers is the quickest and easiest way to shoot yourself in the foot using C++.

Kevin Pang
Can you give a spectacular example?
TonJ
How is this specific to C++ and not C?
Max Howell
+1  A: 

The most spectacular way would be to use template driven meta programming. A simpler way would be to override operators and use them without specifying '(' ')'.

On a different note, modifying the header files without changing the .cpp files should also do the trick. Some call this incomplete coding.

questzen
A: 

Not calling delete or delete[]

Adam Tegen
Couldn't agree less. I use RAII classes or GC for virtually all my memory allocations; if I have to call delete or delete[], it's usually because I'm doing something wrong.
DrPizza
A: 

Overloading * or ->

Adam Tegen
Can you give an example? A smart pointer must overload * and ->, so that does not count.
TonJ
+10  A: 

Not having a virtual destructor on a base class.

Adam Tegen
Why dont we just spout off all the chapters in Effective C++ by Scott Meyers... :)
Steve Duitsman
There is nothing wrong with that if your Base class is not designed to be used polymorphically.
Comptrol
Oldie but a goodie :)
StackedCrooked
+1  A: 

I cut my teeth on assembly, then C, then C++, then C#. I think of C as a clean set of macros for an assembly language. Which I actually like, because I understand every nook and cranny of it. C++ opens up a ton more tricks, but everything in C is still also available. C# finally got wise to this, and even though it still looks very C-like, it blocks some low-level C-type constructs.

One of the thorniest problems I ran into on a huge C++ app turned out to be malloc/free versus new/delete. Anything that's malloced has to be freed, and anything that's newed has to be deleted. But the compiler can't launch flares if something was inadvertently mix-and-matched, so bizarre memory corruption problems can lurk for years. Good luck finding that in your debugging sessions or code reviews.

Well der's your problem. Suggest someone with the rep adding advice here. "huge C++ app" + "malloc/free"? 1) malloc+free should be banished in C++ apps. 2) use smart pointers.
Aaron
2) Use smart pointers, or make sure to free the memory in the destructor.
TonJ
+19  A: 

I love C++ for the flexibility that it offers, and with the arrival of libraries such as BOOST it is becoming easier to piece together a powerful application with most of the time spent concentrating on the business logic.

However, here are some common examples where code will compile but not do what was intended.

1) Overriding Functions

class Base {
  virtual void foo () const
  {
    // Default beahviour
  }
};

class Derived : public Base {
  virtual void foo ()
  {
    // Do something useful for Derived
  }
};

It was almost certainly not the intention of the author that 'foo' in the derived class does not override the 'foo' in the base. You have to make sure your testing is really up to scratch to make sure that you can detect that Derived::foo is not being called!

2) Operators that short-cut except when they don't:

class A {};
A foo (int * i)
{
  *i = 0;
}
bool operator && (int *, A const &);

// ... lots of space between declaration and usage

void bar (int * i)
{
  if (i && foo(i))
  {
  }
}

Others have mentioned operators, but there are 4 which are especially problematic. In the above example rather than having the usual "evaluate the first operand and if true then the second" what we actually have is a function call operator&&(i, foo(i)). The first argument i and the second foo(i). Both will be evaluated (in some unspecified order) and this will result in a null pointer dereference in foo. The other operators to watch out for are, logical or (||), comma (,) and unary &.

3) Class member initialization that doesn't initialize:

class B
{
public:
  B ();
};

class A
{
public:
  ~A();

private:
  B b;
  int i;
};

The above class the non-POD member i is not initialized by the default constructor for the class. The same applies if the constructor was written as:

  A ()
  {
  }

or

  A ()
    : b ()
  {
  }

Of course - what you need is some form of static analysis tool which will catch all of these niggling problems for you! ;)

Richard Corden
easy on the advertising man :P
Ruben Bartelink
or you could use a language that doesn't let you shoot :)
Spence
@Spence. To be fair, I think C++ doesn't deserve to be singled out with this label. I'm not suggesting that you cannot shoot yourself in the foot, the point is that you can do so in 99.9% of languages, its not specific to C++. Unless of course you want to do all your development in SparkAda!
Richard Corden
+6  A: 

Casting a pointer to a type that something isn't. Then calling a virtual function on that type. Depending on how "lucky" you are there may be a function at that location in the vtable that has the same parameters. I've done this where the debugger was stepping through the wrong code. Totally perplexing. If you aren't so "lucky" then it will just crash with a corrupted stack depending on the calling conventions.

Matt Price
I consider crashing immediately at the point of the mistake to be lucky.
Lou Franco
Agreed! The earlier the error manifest itself the better. That's a reason type safety is important.
Matt Price
+13  A: 

Programming serious C++ before you understand it. Sadly it's reputation for being an experts only language is well deserved.

Please, please, please read Effective C++ before you touch production code.

Matt Price
+13  A: 

Returning references to temporaries. Usually this happens when you accidentally copy-construct along the way. Something like:

string MyVal()
{
  return _val;
}

string& GetVal()
{
  return MyVal();
}
Lou Franco
+6  A: 

Violating the Principle of least astonishment. For example operator + should add things together. If you have it do subtraction it will really confuse people and cause them to make stupid mistakes. Or as Scott Meyers put is, do as the ints do.

Edit: the quote from Meyers is from Effective C++, in my copy of the 3rd edition it's in item 18 page 80. "Clients already know how types like int behave, so you should strive to have your types behave in the same way whenever reasonable...When in doubt, do as the ints do." Go read/re-read item 18 today, and be a better programmer!

Matt Price
I like that quote! When I Googled it, I saw quite a few mentions, but not the original. Do you know where it's from?
TonJ
@TonJ Effective C++, I think. Or "More Effective C++". Anyway, the item where he says that operator+ should return a "const Foo", because a+b = 3 is not valid for ints, so it should not be valid for your user type either.
rlerallut
+1  A: 

Creating a buffer overrun vulnerability.

There are few things worse than opening up a code execution exploit to any user who can input data into your program.

Wedge
+16  A: 

In C/C++, if you start a numeric constant with a zero, it's interpreted as octal:

int a = 123; // Decimal 123
int b = 0123; // Octal 123, decimal 83

I've never seen this result in a bug, but once when I was hand-editing a large block of data for an array, I typed leading zeros for some of the constants just to pad them to length. If none of them had an 8 or 9 (which is invalid for octal), it would have compiled cleanly and definitely would have not worked right.

KeyserSoze
bitten by that one +1
EvilTeach
Inherited from C (where it's just as much of a problem), and not specific to C++.
David Thornley
+1  A: 

Using raw pointers without documenting ownership. Two typical cases are having a function that returns a pointer without documenting whether the caller takes ownership of it, or having a function that takes a pointer as a parameter without documenting whether it takes ownership of the pointer. (The entity that has "ownership" of a pointer is responsible for deleting it.)

Using smart pointers is a good way to avoid these problems.

Martin Vilcans
I did vote for your answer, but I disagree with your last sentence. Alas, using smart pointers does not mean you never have to worry about ownership again.
TonJ
+7  A: 

Something to blow the whole leg for sure, with std::map for example:

...
for ( pos = c.begin(); pos != c.end(); ++pos) {
  if ( pos->second == something) c.erase( pos);
}
...
dmityugov
+3  A: 

Forgetting that == has precedence over bitwise operators like & and |. As in:

if (x == y&1)
{
Milan Babuškov
+7  A: 

Using auto_ptr not knowing (or forgeting) that the assignment operator transfers ownership

void Foo(auto_ptr<string> val)  
{  
  std::cout << *val;    
}  

int main()  
{  
  auto_ptr<std::string> a (new std::string("abc"));  

  auto_ptr<std::string> b = a;  // a is erased !  

  Foo(b);  // b is erased also !!! (always use references in method signatures with auto_ptr)  
  ...
}
Pascal T.
And that's also why we don't refer to it as 'the equal'-operator. Assignment-operator is good in general. The transfer-ownership-operator is good for std::auto_ptr...
Andreas Magnusson
Do you know that auto_ptr will be deprecated in C++0x? There'll be a new "unique_ptr<T>" that makes use of new features of the language and does not have auto_ptr's problems.
TonJ
+13  A: 

While this is not foot shooting, I flipped out when I saw a really experienced C++ programmer do this:

((SomeClass*)NULL)->SomeMethod();

Which is actually perfectly fine, as long as SomeMethod doesn't access the this pointer or call any member functions (which in this case it didn't).

Still, that kind of thing is pretty much GUARANTEED to blow the leg off the next programmer that modifies that class.

Orion Edwards
Makes you think why the creator of SomeMethod() didn't declare it static. This way, you'd call it as SomeClass::SomeMethod(), and all is well.
TonJ
Actually, it might be safe to call other member functions as well. After all, they'd get the same problem: it blows up the moment you *need* a this pointer. Could be a cast, could be a virtual call, could be anything. Even a compiler switch changed.
MSalters
The method had some code, then literally had an if( this == NULL ) return; and then some more code. Like I said, I flipped out :-)
Orion Edwards
Nice job interview question: "You find the line 'if (this==NULL) return;' in some code. What could the writer of this line possibly have intended?"
TonJ
Shouldn't it be static_cast<SomeClass*>(0)->SomeMethod();
Nikolai Ruhe
Nikolai... I think you miss the point...
Orion Edwards
+3  A: 

Obfuscation. Things like automatic constructors that do too much, overriding operators, throwing exceptions, etc. Even macros to some extent.

C's beauty is that you can look at a snippet of code and have a very good idea of what the assembly does. Java's (or C#'s) beauty is that you don't have to. C++ can be abused to become the worst of these two worlds -- code that needs to be understood at the level of assembly, but is opaque.

Moishe
+4  A: 
the dreaded trailing semicolon after a for loop:

for(i=0;i<1000;++i);
    print("i=%d",i);

output is 'i=1000'
KPexEA
+5  A: 

Circular header dependencies.
If you're not familiar with the pattern of errors that arise from this situation you can go on for hours trying to figure out what the hell is going on.

shoosh
Before C++, I used Pascal, which makes a clear separation between interface and implementation. And there was a difference between `uses` in the interface and `uses` in the implementation. In C++, headers (should) contain the interfaces and .cpp files (should) contain the implementation. (continued)
Eduardo León
+5  A: 
#define true false
Causas
+3  A: 
delete this;

I can't begin to describe the pain and suffering caused by that one line of code.

Andrew
I disagree ... "delete this;" is used extensively in COM classes, when a call to Release causes the reference count to reach zero.
Carl
delete this has legitimate uses, I don't see anything particularly painful about it. Can you elaborate?
DrPizza
+47  A: 

Originality, eh? Well how about Multi-Dimensional Analog Literals

Tighten your seatbelt and click here

There is real code behind these (see bottom of post). I only wish I had an ounce of that much creativity.

Example:

  unsigned int c = ( o-----o
                     |     !
                     !     !
                     !     !
                     o-----o ).area;

  assert( c == (I-----I) * (I-------I) );
Michael Easter
Very nice one. I'm going to use analog literals in my code from now on! :)
Eduardo León
Has anyone ever put this to legitimate use? That is certainly interesting...
TURBOxSPOOL
Holy crap! I had to look thrice before I could parse that example.
Kawa
Nice! I wonder was that programmer one day like "hey! I want to have some compilable 3D ascii graphics in my code"... :)
AareP
Holy crap, this isn't a joke! That's terrifying and fantastic at the same time! O_o
DoctaJonez
+1  A: 

Unnecessary use of threads.

David
That probably applies more to other languages, where starting up threads is easier than in C++ (not that it's difficult in C++ mind you).
Ben Voigt
A: 

Some of the things described in this quiz

Dan
+14  A: 

Accidentally instantiating an RAII object as a temporary, for example:

boost::mutex::scoped_lock(m_mutex);

instead of

boost::mutex::scoped_lock guard(m_mutex);

No errors, no warnings, just mysterious intermittent runtime errors.

fizzer
being there, done that
aaa
+2  A: 

Using default values for fuction void Func(int i = 0, bool x = false){...} which is only declared in the header file.

Then trying to track the place where you get false from the 2nd parameter.

Dror Helper
+1  A: 
static void MyInterruptServiceHandler(/* ... */)
{
    SomeObject p; // allocates memory in the constructor
    // whoops!  There goes my heap!
}
plinth
+4  A: 

Different versions of struct in different modules, either because struct is defined in two places, or because the definition has changed and one of the modules was not recompiled (dependencies error). This can cause some fun behavior, such as the value of a field being different inside and outside a function call (we saw it in this question).

Arkadiy
Yep. Try passing FILE* structures between a DLL compiled with VC7 and one compiled with VC6. The horror, the horror...
rlerallut
A: 

An infinite loop :P

Also, leaving orphan nodes is a pretty rocking way to hurt yourself.

Joe Morgan
As far as I can tell, you can have these problem with any languages.
Martin Cote
+3  A: 
MyObject* A = NULL;
MyObject* B = NULL;
if (A == B == NULL)
{
 //do something
}
else
{
              //do something else
}

You'd wish this if-statement would be the equivalent of saying

 if ((A==NULL) && (B == NULL))

but you'd be wrong.

SauceMaster
+4  A: 

This:

MyObject* DoSomethingNotSoClever()
{
  MyObject object;
  return &object;
}

Doh, object gets destructed and becomes invalid the moment this function returns. If the caller tries to access the returned pointer, they're accessing garbage. It may work for a while until at some time later everything will go bang.

Scott Langham
+1  A: 
while (1) {

// lots of condition tests that don't cover every condition.

}
Michael McCarty
+1  A: 

Non-const references as arguments are evil as it's non-obvious (from just reading the code at the callsite) that an argument is potentially being modified.

E.g., given:

void do_something(int& foo);

and from reading code at the callsite:

int x = 5;
do_something(x);

it's non-obvious that x could be modified by do_something().

Steve Lacey
+3  A: 

Operator overloading can be pretty evil. Say you overloaded the operator '*' and you need to modify the implementation/contract. Now, being a good coder, you'll go and check all the uses of the overloaded operator.

Ever tried grep'ing for '*' over a large codebase?

Steve Lacey
I don't remember if I've ever grepped for 'operator\\*'.
Windows programmer
+2  A: 

Returning pointers to local variables:

const char* getStr(...)
{
  char buf[128];
  return buf;
}

I hate that c++ allows you to do stuff like that without any kind of warning. It is the only thing that needs fixing in c++ - error reporting and warnings.. C++ was apparently programmed by people with mentality "He who make mistakes must suffer"...

AareP
If only suffering were a zero-sum game, that would be an excellent paradigm. I know far too many languages where the suffering is inflicted solely on the users. Unfortunately, while C++ makes the programmer experience the users' pain, it doesn't actually reduce the pain felt by the users (unless you count making the pain quicker).
Ben Voigt
A: 

If you go above or below the size of your arrays, then C/C++ will access different things in memory. For example the following code will replace the value of a variable in outside the function.

#include <stdio.h>
#include <stdlib.h>

void f(int x) {
    int a[10];
    printf("a[20] is at address 0x%x\n",(int)&a[20]);

    a[20] = -1; /* change variable answer in main (gcc4.3.2/linux/i86)  */
}

int main(void) {
    int answer = 42;
        printf("answer is at address 0x%x\n",(int)&answer);

    f(5);
    printf("answer=%d\n", answer);
    return 0;
}

Even worse is the following, which will change the place the function returns to, to skip a password checking if statement:

#include <stdio.h>
#include <stdlib.h>

int check_password() {
    char buffer[8];
    printf("Enter password: ");
    gets(buffer);
    int i;
    int * p = (int *) & buffer[20];
        printf("*p is %x\n",*p);
        *p += 4; 
    /* change function's return address on stack (gcc 4.3.2/Linux/i86) */
    return strcmp(buffer, "secret") == 0;
}

int main(int argc, char *argv[]) {
    int k = 7; 
    printf("size of address %d\n",sizeof(int *));
    printf("function main is at address 0x%x\n", &main);
    if (check_password()) {
     printf("Authenticated\n");
    } else {
     printf("Password Incorrect\n");
    }
    printf ("bye\n");
}
Marius
A: 

Let's see, some interesting things you can do.

Non-explicit type conversions, including constructors. If your class Foo can be converted into a Bar, like Bar::Bar(Foo f), then any function that works on a Bar will work on a Foo, not necessarily correctly. Something like explicit Bar::Bar(Foo f) will work much better.

Overloaded functions that do different conceptual things, depending on the type of the operands. A function Draw(...) that put images on the screen for most things but deployed a gun when used on another thing would be an example.

Similarly, operators that do non-obvious things. operator+() works fine for adding ints and floats and other sorts of numbers or vectors or whatever, or for concatenating strings, but if you use it for anything else, you're setting yourself up for trouble. A related case is turning short-circuit operators into functions, such as operator&&(), which will now evaluate both its operands rather than the first and then possibly the second.

David Thornley