10 ms·
Q: Why can I access an out-of-scope C++ var? A: So you rent a hotel room...
- ConceitedCode 15y agoTitle is a bit misleading... but still a great answer.
- zrgiu 15y agoI think the title is perfect. I didn't expect anything else when I clicked it. And it's so properly formed, it makes you really curious :)
- briandoll 15y agoGreat analogy and well written. We often see attempts at this style of explanation, but we usually fail at one or both of those qualities. While I wish I saw more of this style of teaching in technical publications, it's admittedly rarely done well enough to convey the point.
- solutionyogi 15y agoEric Lippert is a prolific writer and is amazing at explaining anything related to computer programming. His blog is a MUST read for every .NET developer: http://blogs.msdn.com/b/ericlippert/ http://blogs.msdn.com/b/ericlippert/ I also follow Eric's activity on SO here: http://stackoverflow.com/users/88656/eric-lippert?tab=activity http://stackoverflow.com/users/88656/eric-lippert?tab=activi... Some of his answers which I liked: http://stackoverflow.com/questions/2704652/monad-in-plain-english-for-the-oop-programmer-with-no-fp-background/2704795#2704795 http://stackoverflow.com/questions/2704652/monad-in-plain-en... http://stackoverflow.com/questions/921180/how-can-i-ensure-that-a-division-of-integers-is-always-rounded-up/926806#926806 http://stackoverflow.com/questions/921180/how-can-i-ensure-t... http://stackoverflow.com/questions/5032081/coding-style-assignments-inside-expressions/5032287#5032287 http://stackoverflow.com/questions/5032081/coding-style-assi... He is on HN as well: http://news.ycombinator.com/threads?id=ericlippert http://news.ycombinator.com/threads?id=ericlippert
- jseliger 15y agoHeads up: the two links at the top go to the same source: Eric Lippert is a prolific writer and is amazing at explaining anything related to computer programming. His blog is a MUST read for every .NET developer: http://blogs.msdn.com/b/ericlippert/ http://blogs.msdn.com/b/ericlippert/ I also follow Eric's activity on SO here: http://blogs.msdn.com/b/ericlippert/* http://blogs.msdn.com/b/ericlippert/*
- solutionyogi 15y agoI don't know who downvoted you, you are correct. I fixed up the links.
- yread 15y agothis one is an eye opener and very humble too http://stackoverflow.com/questions/2186595/c-is-there-a-difference-between-return-myvar-vs-return-myvar/2187498#2187498 http://stackoverflow.com/questions/2186595/c-is-there-a-diff... edit: also thanks for making me spend probably next several hours reading through all that stuff :) edit2: oooh this one is good as well http://stackoverflow.com/questions/3110154/why-is-the-explicit-management-of-threads-a-bad-thing/3111104#3111104 http://stackoverflow.com/questions/3110154/why-is-the-explic... edit3: Not from Eric but check out this C# code: sbyte[] foo = new sbyte[] { -1 }; var x = foo as byte[]; // doesn't compile object bar = foo; var f = bar as byte[]; // succeeds var g = f[0]; // g = 255 edit4: oh and check out this description of c# compiler actions http://stackoverflow.com/questions/1917935/how-does-c-compilation-get-around-needing-header-files/1918663#1918663 http://stackoverflow.com/questions/1917935/how-does-c-compil...
- wheels 15y agoLocal variables in C and C++ are just put on a stack (i.e. the stack) and its behavior is pretty predictable. For example: #include <stdio.h> static int *foo(void) { int i = 42; return &i; } static int *bar(void) { int i = 43; return &i; } int main(void) { int *f = foo(); /* with next line commented out prints 42, with it, 43 */ bar(); int i = *f; printf("%i\n", i); return 0; } Until you've made another function call that reuses that space on the stack you'll almost certainly still have valid values when accessing those local variables by address. Things are a bit vaguer in C++ where those variables may be objects which have destructors which have already been called. Edit: Made it predictable, per caf's (correct) comment by adding: int i = *f;
- caf 15y agoIt's not entirely predictable, because, for example, the compiler may have already stored the first parameter of printf (the address of "%i\n") before it gets around to dereferencing f, and it may have stored it in the same location on the stack that was used for `i` in foo and bar. It's also possible that foo() got inlined, so that the space used for `i` in foo() ends up being used for `f` in main.
- pvarangot 15y agoAlso compiling with heavy optimization (such as -O3) can blow a variable out of the stack and into a register that can quickly get reused, or can also inline functions. Both of this can break the perceived predictability. In fact, here on my computer, your code example behaves differently when compiled with gcc default optimizations and when using -O3. [peter@laptop ~]$ gcc test.c -o test [...] warnings [peter@laptop ~]$ ./test 43 [peter@laptop ~]$ gcc -O3 test.c -o test [...] warnings [peter@laptop ~]$ ./test 42 I'm inclined to believe in this case this is happening due to function inlining, but I haven't checked the assembly. Edit: My post refers to the last version of your code, with the int i = *f; line in it.
- alain94040 15y agoIn embedded systems where interrupts are handled from user space (or the code you show is in the kernel), then it is guaranteed that your stack will be obliterated if an interrupt occurs at the exact right time, so your value will not be there. This is not academic: I have debugged code that relied on that behavior, and would fail once in a million runs. Very frustrating to figure out.
- codexon 15y agoI'll probably get downvoted, but I think elaborate real-life analogies like this are more likely to confuse novices than help them. A better explanation in my opinion is to draw a diagram of a stack and showing that returning from a function just decreases a pointer. C++ programs don't scrub the top of the stack once you finish a function because it is a waste of time. If another function was called before the 2nd call to foo(), then the variable on the stack would be overwritten.
- pyrtsa 15y agoYeah, the hotel room analogy breaks as soon as you realize that visiting some completely other hotel room will already overwrite that variable in the first one. But it was a fun story, though.
- schleyfox 15y agoWhile that is more accurate and I think that programmers should understand how computers work, as well as C calling conventions, in this case the analogy helps. People who know what the stack is (other than something that can be overflowed) as well as how functions are implemented would likely never think to ask this question. By the time you give the satisfactory "real" answer, you've written the better part of an intro architecture lecture (at my school, I think we probably had 2 or 3 lectures and a lab to get to this point, with other digressions). The real explanation would also be less complete than the analogy as going into the "construction of a football stadium", etc. would have to consider optimizing compilers, virtual memory, and the other things that could get really mucked up. The analogy is accessible even to people who don't program, rather than to just those who have seen %ebp and %esp.
- wh-uws 15y agoLet me preface this by saying I am not attacking you just stating an opinion about the sentiment Thats the exact type of thinking that keeps so many people away from programming and computer science. A nice accessible answer that helps a person make a logical leap in the right direction is so much more important to a novice than pedantry. Its not a perfect answer but to a person who has no clue whats going its a lot more helpful to get some idea
- dools 15y agoI'm not sure I agree entirely with this explanation. He emphasises that this is unsafe behaviour that is protected against in safer languages - I've never heard it said that the use of pointers should be considered unsafe and there are also pointers in other languages that exclude things like multiple-inheritance and have garbage collection (which could be considered safer languages). I like the room key analogy (almost) but I don't think it needs to be stolen and I don't think all the talk about policies and contracts is necessary at all. It could simply say the thing you're returning is not the local variable. It is a pointer. I have a box and instead of giving you the box I give you a key to the box. Anytime you want to use the contents of the box you must come over to the box and open it, but you can't take the box with you. If you want to put something in the box you just walk over and put it in - but here's the rub: you have no guarantees that you're the only one with a key. I could give out the key to a bunch of people so you don't know what will be in the box and who owns it. Use with caution!
- stoney 15y agoI think he means that pointers are unsafe in the same way that dynamite is unsafe. They both have legitimate uses, but you need to be very careful when you are using them. (Rather than unsafe in the sense of don't use them at all). I like your box analogy, but I don't think it goes far enough - with C++ pointers it is not always ok to put something in the box. If the pointer is out of date or invalid there is a chance that writing to it will make the OS kill the entire process. Languages with garbage collection don't tend to have that kind of problem, since whatever is at the memory location will stay at that location until everyone surrenders their pointers.
- maranas 15y agoI agree with you for the most part. C/C++ lets you do what you want, presumably because you know what you're doing. But I don't agree that pointers are evil, and should be avoided. If you want to do any practical programming with C/C++ at all, you have to learn how to dynamically allocate memory and use pointers. Generally, pointers work as advertised. It's the cases where they work when they shouldn't that is the problem. In these cases a compiler usually warns you, so you are still covered. So in C/C++, just because it works, doesn't mean your code is right.
- stevetjoa 15y ago200 upvotes in nine hours?! Is that a Stack Overflow record?
- leon_ 15y agono, I guess many people started to understand this behavior just now. (something you don't meet when all you do is javascript and ruby/python)
- DrJokepu 15y agoMaybe I'm an elitist but I find it rather scary that people write code for a living without understanding concepts such as this. It's easy to forget what a huge service StackOverflow provides to the developer community by spreading knowledge in an easily accessible and entertaining fashion.
- roryokane 15y agoIf those people who write code for a living never program in C++ or other languages with pointers, instead using languages like Java and Python, I wouldn't expect them to know what happens when you mess around with pointers in C++. If you don't use pointers, and your language doesn't even support pointers, why care about the behavior of pointers? Understanding the simpler concept of "references" is good enough.
- leon_ 15y ago> I find it rather scary that people write code for a living without understanding concepts such as this It's scary but the industry is full of such people. In germany here it's really bad as we have 2 ways to become a (official) professional programmer: 1) Studying CS at the University 2) A 3 year apprenticeship where you learn to be a state approved "computer scientist with a specialization". Way 2 is still pretty popular and though not all people going way 2 are bad there's not much fundamental CS theory you learn there. You work for 3 years in a company where they teach you their way of software development (and you have blocks of school lessons every few weeks). The education is pretty lacking in fundamental theory. The people only learn either .NET or Java (depending on the shop they are working in). It's not uncommon that people can't tell you the difference between long and double (other than that one can has a decimal point). Don't start about pointers, manual memory management or things like stack frames/stack layouts. And they don't want to know that stuff. "Why should I learn that? The compiler/runtime does it for me!" is often an answer you hear.
- yaakov34 15y agoI say this as a C++ programmer (C++ is essentially the only choice in the domain in which I currently work), but this really underscores how unreasonable C++ is for writing secure/high reliability applications. On the one hand, the compiler will curse you out for trying to use a non-const iterator in a const function (sheesh, what kind of an idiot are you, anyway)? On the other hand, you can read and write to every bit of memory allocated to your application, and it will stand by and do nothing. I think the number of applications which had buffer overflows at least at some point is statistically indistinguishable from 100%. Try this hotel analogy: you go to a hotel in which you once stayed, and tell them that you're going to dump every bit of possessions and furnishings in all the rooms outside on the street, rifle through them, set them on fire, then photograph all their guests in the nude and distribute the pictures. Most hotels will object. C++ won't.
- ANH 15y agoFWIW, the Clang compiler does warn about this situation: undefined.cpp:4:13: warning: address of stack memory associated with local variable 'a' returned return &a; Edit: So does gcc.
- yaakov34 15y agoNot nearly enough. Note that C++ combines C's vulnerabilities with non-transparency. Suppose you have a data structure like "set of maps of strings to pointers to vectors." That's actually not a complicated structure for a modern application. Now suppose the new guy on the team, who is working on a function which is not taking user input and is not security-sensitive in itself, puts a pointer to a local variable in this structure. Now you, writing a security-sensitive function, write something to this structure. You're overwriting the stack, and NOBODY will warn you or do anything about it. You're certainly not going to get a compiler warning, and I don't think the "new guy" got one either when he did this - he was not directly returning the pointer. This means that you need to treat every line of the application as security-critical. Some people do, but for most, it's not realistic. There are some tools and techniques to help you, but it's not 100%. And it needs to be 100%, since the attacker needs 1 entry point.
- city41 15y agoEric Lippert was one of the highlights of working at Microsoft. He was (and I'm sure, still is) very active on the internal C# mailing list. His answers are always very entertaining to read. He has a smugness that is deserved and not irritating (mostly :)), and inside the walls of MS he turns that smugness up quite a bit higher.
- ericlippert 15y agoI'm glad you enjoyed my answers; however, I am never intending to come across as smug. It is difficult to get across subtleties in an impoverished text-only medium; it has certainly been my experience that instructive and constructive criticism can easily be read as smugness. It's also been my experience that trying to deliberately make it sound less smug often just turns it into sounding like condescention. Text-based communication of technical issues is a hard problem and I do struggle with finding the right tone. Thanks for the feedback.
- city41 15y agoI don't think "smug" is quite the correct term. I meant nothing negative with my comment (and was teasing with the "mostly"). You do have an "air of authority" about your answers, but that authority is clearly earned. I enjoyed your answers on the C# mailing list quite a bit.
- jamesgeck0 15y agoI had a roommate in college who would write code like this. I (and several other people) tried to explain to him that he couldn't necessarily count on the pattern working all the time. His response was to say, "But it works here!" and continue abusing C++'s undefined behavior. I stopped giving him help with his CS coursework in fairly short order.
- thewisedude 15y agoA good analogy no doubt! But you should be careful when using analogies. Every behavior of the analogy might not be applicable to the original problem. Analogies can only help make people "understand" something. Normal brains try to relate things to what it has learnt so far. So analogies seem to help. Analogies in themselves are not scientific explanations obviously. A scientific/rational explanation to the question posed by the user would be - C++ makes no promise about the behavior of the program when out-of scope C++ variable is used. Obviously this explanation -a simple one is quite less dramatic.
- skrebbel 15y agoif you can always legally access the book, which will for sure be available to you in that drawer, then the hotel key you stole must be a closure.