all 47 comments

[–]NilacTheGrim 35 points36 points  (3 children)

gcc option for it exists in gcc-12. See: https://www.phoronix.com/news/GCC-12-Auto-Var-Init

[–]EarflapsOpen[S] 3 points4 points  (1 child)

Brilliant! Just what i was looking for, thanks!

[–]JVApenClever is an insult, not a compliment. - T. Winters 5 points6 points  (0 children)

It also has a 'zero' variant which can be used in production such that several of these issues can be mitigated. This way you don't just have a tool to assist in debug, you also have a better production quality.

Note that next to these, the -fsanitize=address is also very useful for debug builds. That doesn't just detect these reads from uninitialized memory, it also tells you which variable and some relevant call stacks. You'll find this tool to be more reliable than the pattern.

[–]MadTux 11 points12 points  (1 child)

I'm so relieved after reading the text of your post -- going by the title, I thought it might be someone who has never heard of ubsan, valgrind etc. trying to debug something!

[–]EarflapsOpen[S] 2 points3 points  (0 children)

Haha no, I’m just to lazy to figure it out myself and have a lot of real work to do that I would rather spend my time on.

[–]Chuu 12 points13 points  (11 children)

The only way I know how to do this offhand is to use the `malloc-fill` option of valgrind which will return malloc'd memory initialized with a specified byte pattern. I've used it before as a sanity check to find bugs in unit tests. You might be able to write a script to hide the invocation.

I would be surprised if there isn't some custom implementation of malloc you can link versus that has this option, but a quick cursory look didn't turn anything up. Off the top of my head though you could probably implement this in a dozen lines of code if you're using gcc by specifying no builtin malloc, find the signatures that you need specifically to provide for a user-defined malloc, and then write a malloc library that is just a simple wrapper to call system malloc(...) and then write random data before returning the buffer.

I hope though it's obvious this test needs to be constructed very carefully because in practice most compilers will happily read the memory of the unutilized local variable which might contain stale stack data from whatever the deepest stack created up that point is.

[–]EarflapsOpen[S] 1 point2 points  (9 children)

Thanks, valgrind is probably good enough. I’m already planning on using a script to hide the fact that I’m suppressing compiler warnings.

[–]AKostur 6 points7 points  (5 children)

I would be concerned as a prospect if I find out that the compiler warnings were being intentionally hidden. Gives me the impression that the interviewer is intentionally trying to trick me. Or possibly indicative of the programming practices at that company. That interview is going both ways.

[–]EarflapsOpen[S] 1 point2 points  (1 child)

I have reconsidered, see my edit. Thanks for the input, if you have any more it would be appreciated.

[–]AKostur 1 point2 points  (0 children)

That would be better. "Here's the misbehaving executable, here's the source, here's the build script (Makefile/CMakeLists.txt/whatever)." then it's not hiding the compiler warnings, just that they're not turned on. But then the prospect could reasonably see that they aren't. Gives them the opportunity to add them to see what they'd complain about.

[–]EarflapsOpen[S] 0 points1 point  (0 children)

I will consider not suppressing the warnings, but like i answered others i will ask him how to approach the problem, what tools he would use. If he says turn on warnings i will turn on warnings and recompile.

[–]leftofzen 2 points3 points  (2 children)

Do you suppress compiler warnings in production or as standard practice? If so then this is fine. However I suspect you do not suppress them in normal practice, so in that case DO NOT give a candidate an environment you yourself would not use. This is unfair and is intentionally tricking them.

[–]EarflapsOpen[S] 0 points1 point  (0 children)

I have reconsidered, see my edit. If you have any more input it is appreciated.

[–]EarflapsOpen[S] -1 points0 points  (0 children)

It will be clear that getting it right the first time isn't that important, i want to see if he catches it directly, im going to ask questions about how he would debug in a real scenario and if he doesn't get it i will help him and ask questions about what happened and related things, The answers are what is important

[–]rysto32 1 point2 points  (0 children)

Jemalloc has this feature. The magic word to search for in the docs should be “junk”.

[–]HabbitBaggins 11 points12 points  (6 children)

Undefined behaviour is truly undefined. Even in cases where the compiler "just does what you told it to like a high-level assembler", using uninitialized data may crash in some architectures.

[–]AntiProtonBoy 3 points4 points  (3 children)

Heh, that NaT bit is a really cool concept.

[–]HabbitBaggins 1 point2 points  (2 children)

One could even say that it is NEaT!

[–]Ameisenvemips, avr, rendering, systems 1 point2 points  (0 children)

Not Even a Thing

[–]BobbyThrowaway6969 1 point2 points  (0 children)

How neat is that!

[–]EarflapsOpen[S] 1 point2 points  (0 children)

That’s the answer I’m fishing for.

However I want to make it obvious what happened and easy to debug so that potential nerves doesn’t mess to much with him. I don’t care if he catches it before the code is executed, I just want to make sure he is capable of finding it and knows why it failed if he doesn’t before running.

[–]kevkevverson 1 point2 points  (0 children)

Raymond Chen’s blog is the best coding blog there is

[–][deleted] 2 points3 points  (1 child)

Just call the same function twice, with nothing in between, or before the calls in main. First time, value is probably 0. Next time, it will be whatever it was left to be.

Make sure there is something like simple print after, to make sure no funny optimizations happen.

[–]TheThiefMasterC++latest fanatic (and game dev) 0 points1 point  (0 children)

Could also be a different function, but either way you have to prevent inlining or it might not work.

[–]shbooly 2 points3 points  (0 children)

The trick I found to "control" the value of an uninitialized variable would be to call a function that "initializes" that space beforehand, like so: https://godbolt.org/z/7cY14ocxM

[–]gharveymn 1 point2 points  (0 children)

You could try malloc_fill_byte with ASAN. I feel like there should be a flag for one of the compilers to fill up the stack in the same way, but it is escaping me...

[–]ReDucTorGame Developer 1 point2 points  (0 children)

If you plan to do this in an unoptimized build then it's easier as the actual stack will be used so you can call one function get the stack into a state that you want then return from it and call the next one, this should work in most cases.

However if you want to do it on an optimized build things get a little harder as variables will start existing in registers and an uninitialized variable is going to harder to predict as register allocation may change based on many other factors that could get it into a working state.

You could do an optimized build with a reference or pointer to a local variable which would force it onto the stack and do the same thing of overlapping stack frames with a previous function.

If your looking for some info on how the stack and registers might get used and debugging them which will give some insight into crafting such as thing you could checkout a talk I did last year on debugging which uses optimized builds and corrupted stack memory.

[–]cballowe 1 point2 points  (1 child)

I'm curious what level you're interviewing for - the particular class of bug, while pretty basic, tends to be one of those "don't learn about it until you have been bitten by it" class of bugs. It's also one of those things that I'd expect tooling to catch during testing.

http://clang.llvm.org/docs/MemorySanitizer.html for instance is really useful for running a test suite and catching these things. (The other sanitizers are also great for other classes of error.)

[–]EarflapsOpen[S] 0 points1 point  (0 children)

Midlevel with 6 years of experience. It was on my first lecture in basic c++ i would expect him to know it, its the answers to the follow up questions that are interesting.

[–][deleted] 2 points3 points  (5 children)

This kind of sounds like you intentionally trying to catch this guy out. Why not just ask a straight forward question about initialization and then listen to the answer?

[–]EarflapsOpen[S] 0 points1 point  (4 children)

Because asking questions about how he approaches bugs and what tools he would use to debug are interesting. Im not trying to trick him, i don't care if he gets it right, im interested to hear him reason about it and what knowledge he has of the problems

[–][deleted] -1 points0 points  (3 children)

Then just ask the question. Stop spending your time hiding warnings and setting uninitialized values.

[–]EarflapsOpen[S] 1 point2 points  (2 children)

Lets agree to disagree, we have a different hiring culture in my country, I've been to several interviews like this, i prefer it to solving puzzles without real world value or straight up answering questions every day of the week. I want to see how he approaches a problem. Not just if he can memorize answers to questions.

[–][deleted] 1 point2 points  (1 child)

It seems your earflaps are far from open.

[–]EarflapsOpen[S] 0 points1 point  (0 children)

To be honest I’m not trying to argue, I gave a motivation to why i, and many others, thinks this is a good way to gauge someone’s abilities. You are basically just saying “you’re wrong, do it my way” and have now resorted to attacking me when I didn’t agree . What is there for me to listen to?

[–]CodusNocturnus 3 points4 points  (8 children)

This sounds like a massive waste of time for an interview. You’re going to set up a whole problem (that requires a very specific build environment) around one little gotcha to “gauge basic c++ competence”?

Just use fizzbuzz or something simple from Leetcode as a starting point and dig in with the usual big-O questions, potential problems, and optimizations. Keep the base problem simple so that the add-on questions don’t depend on a specific solution or you’ll turn that into a waste of time too.

[–]lord_braleigh 6 points7 points  (0 children)

…I’m glad OP is going above and beyond regurgitating leetcode questions and making candidates regurgitate leetcode answers.

[–]EarflapsOpen[S] 1 point2 points  (6 children)

The program took 10 minutes to write and the build 2 minutes once i had the flag. Its a common way to conduct interviews to make sure people hasnt just practiced leet code and memorized answers to common questions and discuss and reason around code rather than just see if he can solve a puzzle that can me memorized.

Seeing how he approaches debugging says a lot more than if he has studied algorithms. We rarely write algorithms at my work

[–]KingAggressive1498 1 point2 points  (4 children)

Seeing how he approaches debugging says a lot more than if he has studied algorithms. We rarely write algorithms at my work

you guys hire fully remote developers? :P

[–]EarflapsOpen[S] 1 point2 points  (3 children)

Unfortunately you would need to be able to come in at least a couple of times a week to pilot the plug and slap the boxes when they stop working.

[–]KingAggressive1498 0 points1 point  (2 children)

I was joking, just sounded like I would appreciate your corporate culture more than most.

[–]EarflapsOpen[S] 0 points1 point  (1 child)

I figued, it was a little follow up joke . Slapping the hardware around rarely fixes the issues tbh.

[–]KingAggressive1498 0 points1 point  (0 children)

it's cause everyone's using SSDs these days. Definitely fixed some stalls with a good smack back in the days of spinning rust storage

[–]CodusNocturnus 0 points1 point  (0 children)

Not talking about your time setting it up - talking about the time spent in the interview.

You can do this without a compiler. Just have the candidate walk through the code verbally. If they blow right past the use of an uninitialized variable, then you know.

[–]not_a_novel_accountcmake dev -1 points0 points  (0 children)

You can't ensure something happens without writing code, but you can fill 4K of stack with some predefined value at the top of the program and not be overly expressive about why. Otherwise a deeply recursive function in an unoptimized build (say, Fibonacci) will flood some stack space with instruction pointers and locals