This is a completely broken C++ interview question. It asks the candidate to reason through a worst-practice, which exposes you to their knowledge of trivia and tells you nothing about whether they can actually get stuff done in C++.
My old Sonicity C++ code, which was built on ACE, is littered with "delete this" calls for Reactor callbacks. Obviously, "delete this" is OK if you're on the heap and you can guarantee that the code isn't going to touch the object again. But what I remember most about that ACE Reactor code was how fragile the event handling was; "delete this" is a recipe for horrible memory corruption flaws.
This is what you get when your C++ interviewers decide that interviews are more about proving how smart they are than about qualifying candidates.
I disagree, I think this actually a pretty good question, if asked properly. If you expect the right answer right away, then yes, it's a useless piece of trivia. But if you ask people to think it through, you might uncover a surprising lack of understanding of what's going on under the hood (stack vs. heap, etc.) If your goal is to have people think it through and explain their thinking along the way, it's not a bad question at all (assuming your goal is to hire someone who knows C++ well - whether it's a good goal is a whole different question).
Even with heap-allocated objects there are lots of cases where you can't safely "delete this", which is what makes it a worst-practice. If you just want to know whether the candidate knows what the heap is, ask them to explain why alloca() is evil.
The more I stare at that question, the more I can't figure out if you mean the obvious or the subtle pitfalls of alloca(). Off the top of my head, some of the potential "evils" I can come up with is: automatic deallocation after the function (and not the scope iirc) RETs, difficulty in passing alloca-allocated memory to other functions, being totally non-thread safe, looks foreign to other devs, classic stack-allocated buffer attacks are easier on certain systems, more pernicious effects from off-by-one errors. Did you have anything else in mind?
The way I thought about it, concurrent access to objects allocated via alloca() would probably not be explicitly protected by a lock. Threads can also be killed and spawned while other threads are accessing its stack contents. Anyway, I can think of more use cases where it's a bad idea to allocate objects on thread's stacks that you're planning to share.
Yeah, sharing objects on the thread-local stack is definitely a bad idea.
But as long as the alloca'd memory is only accessed from within the same thread, it is -- AFAIK -- safe to call alloca() simultaneously from multiple threads, the same as malloc(). I think that qualifies as thread-safety by the usual definition: i.e. the function doesn't access statics or globals.
(Of course this will vary depending on the CRT. I don't think any UNIXes nowadays ship without threading support in the CRT, but Microsoft Visual C++ used to have separate thread-safe and non-thread-safe C libraries.)
If someone can explain what happens, then one of two things is probably true: they've purposefully memorized an edge case for the sake of trivia, or their knowledge of language semantics and runtime behavior is deep enough to figure out what happens in an unusual circumstance.
I agree that doesn't tell you if the candidate is good at solving problems using C++, but there is potential to discover how deep their understanding is.
It also selects for developers who deliberately code up to the limit of what the runtime will allow, regardless of the obvious fact that having code like this is like sprinkling landmines across your product.
When you're looking for an expert in a field, do want to find someone that claims to know what they're doing because they read a book somewhere? Or do you want to find a seasoned pro that has actually tried and possibly failed using different techniques? Their failures may give them more insight and experience than their successes. Especially if they can tell you what they did to improve themselves afterwards.
Becoming an expert has far more to do with knowing how to get things done in a known time frame than knowing every little piece of triva. One you code in the same language with 3 or 4 compilers you start to look at edge cases as a dangerous no mans land to be avoided if at all possible.
PS: I worked with code from the 1984 Macintosh days that was still in use in 2005. You could see where people had updated from Motorola 68020 to PPC and if it had not been stripped out some poor coder might have updated the remaining ASM to x86.
It's been years since I worked with C++, but my recollection is that C++ programming involved a lot of memorization of edge cases just as a guard against running into them.
...it's probably a good interview question for a C++ compiler programmer?
I just figured a good language lawyer, like a good real lawyer, would be able to both interpret the law (spec), but also tell you what would happen in reality if you violated it a certain way.
This is a bad interview question for another reason -- I don't consider myself to be a good C++ developer and I answered it correctly. This is only because I reversed enough C++ code to understand how memory allocation, vtables and compilation works and have a decent grasp on implementation of object oriented languages. Would I make a great C++ developer though? Probably not in my definition of a "great developer."
For me, I've always thought that the 'greatest developer' was really the one that was the greatest at debugging. Any developer can write code, but my experience has shown that only a subset can properly diagnose issues to find their root cause. Those on the team that can do that will save you huge amounts of time and money because things will go wrong (especially in C++).
If you add up all the time it takes to write a particular system, I think you'll find debugging and fixing bugs to be one of the largest chunks of time, probably beating out the time it actually took you to write and possibly design the system. Obviously a design more suited to maintainability will decrease this somewhat.
Given this, I'd say this is an excellent question. Especially if the interviewee can tell you why it's a bad idea, or what the gotchas are with using 'delete this;'. It might not find developers with other positive characteristics like what makes for simple and elegant designs. But if you have a mix of questions to cover the many aspects of development in the interview, you should be good to go.
IMO, that's not a bad question. C++ is not my thing, but I don't see anyone mentioning.
A) Running the code on another system to double check that the systems memory / OS has not been corrupted. I once wasted ~6 hours on a corrupted production box, so now the new rule is when system call fail double check it's not just the machine.
B) Double check that none of the memory allocation / book keeping memory had been over written, memory had not been freed twice etc.
Honestly, I usually try to do that type of stuff by direct code inspection. If it's failed once I am probably going to need to debug related code in the not to distant future so really understanding what's going on is important, but hack and slash debugging can be fun.
Since we're chiming in on possible solutions, why not do the most general thing first? Check memory usage of the system and process right before segfault, check environment variables that govern malloc behavior (i.e. MALLOC_OPTIONS, OS X-specific ones), check if using (s)brk() system call succeeds right before that, check ulimits.
Then you can either litter break points and start stepping or load the core file in gdb, and start looking closer.
This feels like kind of a cheap answer, but I know that with Visual Studio you can step into most standard library functions, even if it ends up being at the assembly level; I assume the same is true for gdb.
Is the not asshole answer to be stopping right before the malloc and taking note of memory consumption and determining how much malloc is trying to allocate?
Stepping through malloc isn't going to help you much in this case. But most people I've met that have written a lot of C/C++ code have seen this bug at least once.
When you start asking about how much memory malloc is asking for, that's a tip-off in the wrong direction for me too; malloc handles "out of memory" pretty gracefully.
I believe the following: in evaluating someone's capacity for implementation in one level of abstraction, their understanding of the next level down is a good indicator (but neither necessary nor sufficient precondition) of their understanding of the whole of the system. I'm sorry for the grammatical awkwardness of the preceding sentence, edits welcome.
Keep in mind he doesn't care if they answer correctly. I think it's a great question. It's always good to ask a question like this, because C++ programmers often have to deal with these dark corners of the language. Knowing the whole language simply isn't an option. I expect candidates to run through the following questions until they can answer one satisfactorily (hopefully without any prompting):
1. Must it work according to the standard?
2. Is there a reason why it can't work?
3. Are you aware of it working or not working in any particular implementation?
4. Reasoning about how the relevant features might be implemented, can you guess whether it would work?
At some point candidates should express any doubts they feel about the advisability of actually using the technique, or about the conditions under which they would use it, and of course they should explain what further research they would do if the question came up in practice.
In my mind, a candidate can get full marks without actually knowing the answer to the question. I would actually prefer them not knowing, because then I'll learn more about how they think and how well they understand C++.
Maybe it's bad at proving how good a C++ programmer someone is, but it's good at seeing how good a programmer someone is.
As the author says, he doesn't expect anyone to get it on their first try. It's more a test of if the candidate can figure the answer out or not. Would you rather have someone who can figure questions like this out on their own or someone who will dismiss this as "trivia"?
Why do posts about interview questions always attract such vehement reactions? The politer replies on the blog itself suggest that the author should work for McDonald's instead of programming. Reddit's discussion isn't much better (predictably). HN can't even have a reasoned discussion about it?
Because people really do not like being unfairly or capriciously judged on interviews. For many engineers, doing well on an interview is very important for their life, and it is extremely frustrating to have a silly or unfair question.
I get that part. But then in order to justify the level of intensity, doesn't that require someone to concede that they wouldn't have gotten the answer to this one? There seems to be more to it; like "I knew the answer to that one, but he could have easily asked a question that would exclude me!" Is there a question he could have posted that would not have elicited this reaction?
> For many engineers, doing well on an interview is very important for their life, and it is extremely frustrating to have a question they cannot answer.
This question and the associated discussion remind me very strongly of something I learned very early in own professional C++ development:
C++ the language is an extremely leaky abstraction. There are so many places where you really do need to think about what the compiler is doing and what is happening behind the scenes rather than thinking at a consistent abstract level.
Is that a bad thing? I suspect that C++ programmers would say no. But then again, there would be a lot of bias in that answer...
As an outsider looking in at the world of C++ development (I work on hardware), my first thought is "Why would you want to use a tool that requires an understanding at that level of complexity for mastery?"
Perhaps C++ has some extraordinary benefits that I don't understand, which makes deleting the v-table before the method returns the stack to the heap worth the trouble [1]?
[1] I might have mixed up some of the terminology a little here. Feel free to correct me vigorously.
C++ is a toolkit for constructing problem-specific languages. You do this by creating new types (classes), using templates, template metaprogramming, preprocessor, multiple inheritance, and all kinds of other stuff.
Once you develop a language, teach it to all your developers and establish a policy to punish deviations you can write very efficient programs - at near or exceeding asm performance (modern compilers are smarter than developers when it comes to CPU-specific optimizations).
Programming in raw C++ using all its features is probably not productive - the code will not be readable by anyone except Stroustroup himself.
Other languages such as Lisp also allow you to create your own language for specific problems, however they are focusing on expressive power and not on performance.
Do you find it useful, in your field, to understand how your tools work? If so, perhaps you might allow that if someone is interviewing for a job using another tool (C++, in this case) that they might be expected to know how that tool works.
Also, with respect, it's fairly clear from your second paragraph that you don't understand the terminology being used at all. Which is okay, it's not your field. But, it makes your assessment of how complex this discussion is somewhat suspect.
Totally agreed about understanding how tools work being useful.
I'd just be wary of using an extremely complex tool. From what I can tell, this "C++" looks like it could self-destruct at any minute, unless handled by an expert. Perhaps that makes the case even more strongly that you ought to filter your hires most strictly, but I wonder whether there might exist a simpler tool that could do the job with fewer risks.
You have mixed up the terminology, vigorously. :) And that is the exact purpose of the question. To distinguish c++ programmers from pretenders. If you don't know C++, the question is nonsense, but if you are going to be writing code, you should understand the execution model sufficiently to answer it.
"Yeah, this one time I double allocated a vtable on the stack of a doubly-linked binary hash."
And by the way, thanks so much for your work on OpenBSD (assuming you are the Ted Unangst of legend). I've been using it for years, and I appreciate the dedication of the folks who created it.
When I was interviewing C++ programmers, we had a C++ test, and some stock questions I asked face to face.
However, I found I could pretty much weed the good C++ programmers from the mediocre/just read about C++ before the interview by asking one question:
"What is a virtual function?"
If they have trouble starting to answer it, give them a hint with "What would cause you to type the keyword 'virtual' in your code?"
You would be amazed how many C++ coders don't really know the answer to this, or what is going on (vtables etc, or even just the behaviour).
One candidate answered "I'd make a function virtual if there were any other virtual functions in the class." It seems like there is no shortage of bad answers to this question. All the people who ever gave me a correct answer (hit rate was <10% of candidates) were good C++ developers.
C++ is my main language these days (and my guess at the answer happened to be correct), but I think this interview question misses the point.
The key to using C++ successfully, like it or not, is not to understand what happens in every possible circumstance (this is pretty much impossible). The key is to carve out a subset of the language (and some usage patterns) that you know how to use and stick with it. I wouldn't use delete this without consulting the documentation first, even if I suspect it's legal (hell, I use "idiomatic" delete maybe once in 5000 LOC)
You know, the more I read suggested interview practices and the responses they elicit, the more I think that the best interview question would be to get the candidate to critique a few interview questions.
The point here is not whether this is good practice, or whether the candidate knows the answer, or whether they would write it themselves, or whether they get the right answer immediately, or whether they automatically know the darkest corners of the C++ spec (of which this isn't one).
The point is whether they can reason through, with the interviewer, and then potentially change their mind if they find that they're wrong.
Part of being a good programmer is finding the good ideas among the dross, finding the right implementation technique among the many at their fingertips, and finding the right design among the myriad plausible constructions.
If you can't find the good ideas in these sorts of interview questions, if you can't read carefully enough to see that the whole point was to uncover whether of not the candidate can reason through then potentially change their mind, or if you think that to do so isn't an important characteristic to test for, then that tells me something.
Yes, it's important to see why things don't work, or are broken, or are a bad idea, but the ability to find good ideas is infinitely more important.
I like this interview question, and if you don't, then we're not a good fit. It doesn't mean you're a bad programmer, it doesn't mean (necessarily (I hope)) that I'm a bad employer/manager/programmer/interviewer - but it doesn mean we probably won't work well together.
But I could change my mind if you provide better arguments than the ones I've seen so far.
I'm cold on C++ (haven't coded in several years) but let me try this out:
deleting "this" releases memory held by the instance data of the object. The programmer can't be sure that any subsequent references to that data will return valid data (although the compiler will allow it). Static data and type-level methods should be fine to call -- although every time the program counter ticks you can't be sure that you're continuing to walk through uncontaminated memory.
I think that's it.
Sounds like a BS question to me because you're going way, way under the hood with exactly how the compiler runs the code. It's like those coding questions where you have to start byte-counting to get the answer. Neat trivia perhaps, but I'd much rather have somebody who delivered clean, organized, easily-maintainable code and got the answer wrong.
EDIT: Seems like I've seen delete this on several occasions (although I can't remember where), but hell if I'd use it unless I had no choice. Even then, it'd be the last statement in the method.
It also invokes the dtors for the object, and, more importantly, does all this before the caller method returns, so that when "delete this" finishes, the program still has to execute code in the method context of a dead object --- which usually works.
I'm a bit rusty on my C++ minutiae, but... there's also the problem that you don't know whether the corresponding new statement was plain new, new[], etc.
Mismatches between new[] and delete will generally just fail to call dtors or potentially call dtors twice, but the behavior's undefined. Ick.
The function's body is not part of the object itself. When you delete the object, you can keep executing the function just fine, as long as you don't access any member variables.
You keep executing the function because it's on the stack. The program counter keeps moving through the method until it hits a return statement. God help you if you try to reference one of the class' internal data objects as their heap space could have been allocated to something else running on another thread.
The function's body is not part of the object itself
Most all of the time, yes. But the function could have been dynamically allocated to an instance of the object. You don't know from the definition of the question. A dynamic function, presumably, would be picked up by the dtor.
Looking over the responses, it is really hard to believe many of the people here have worked in C++. This is basic style for anyone who has ref counted, such as implementing IUknown.
I'm torn on whether this is a good question or not. The important part of the question is definitely the "why?" step. Finding out whether a developer will question their own assumptions, fall back to solid knowledge and ask questions to acquire the knowledge needed to proceed or if they will simply bumble down the garden path of ignorance, making things up as they go with no basis in fact other than a gut feeling is very important.
It's just a language-specific variant of a 'Microsoft problem': you don't want the answer, you want to watch the process. It's similarly useful in theory. But in practice I think it has the same key failing: Performance is too skewed in interview situations for it to give you consistently useful insight into candidate fitness.
If you want to thin out a hundred otherwise-equivalent candidates - knock yourself out. But at that point you might as well be flipping coins.
I always find it curious when the number of comments on an article exceed that of the point value. It leads me to suspect that users get angry over the article for some reason.
To add to the discussion, however, I knew the answer because I had a run in with doing this sort of thing. I had built a simple game with OpenGL - stuff moved around on the screen and you could shoot it. Due to the way I constructed the objects, it was trivial to "Delete this" when the object should disappear - a bullet collides with an enemy, perhaps. I did it, it worked exactly as expected.
The follow up question - "What can you do after delete this; ?" - also reared it's head, and that's when I found the other edge to the sword and shied away from it's usage.
At the level of this question, checking out Scott Meyer's 50 ways will show you some that he got wrong. An interesting one is how to write a smart pointer class, and how many ways it can go wrong.
My old Sonicity C++ code, which was built on ACE, is littered with "delete this" calls for Reactor callbacks. Obviously, "delete this" is OK if you're on the heap and you can guarantee that the code isn't going to touch the object again. But what I remember most about that ACE Reactor code was how fragile the event handling was; "delete this" is a recipe for horrible memory corruption flaws.
This is what you get when your C++ interviewers decide that interviews are more about proving how smart they are than about qualifying candidates.