-3
void go()
{
    //{1}
    char buffer[2];
    gets(buffer);
    //{2}
    cout << allow;
}

I tried to run the procedure above in 2 cases:

-1st: I declare "int allow;' at position 1

-2nd: I declare "int allow;' at position 2

In both cases, when i tried to enter the string "123" (without the quotation marks), the allow's value was 51. However, as I read about the memory layout, only in the first case, the position of "allow" in the stack is before buffer, which means that when the string is longer than the buffer, the value of "allow" is changed.

Then, I tried to declare "char sth[10]" in both position. This time, only when I declared sth in first position, the value of it was changed.

Can anyone explain what happened?

user3425082
  • 129
  • 1
  • 2
  • 9
  • Did you set allow to any other value before `gets...`? – Amit Jul 02 '15 at 12:10
  • 5
    There is no guarantee how the variables are laid out in memory based on where they are declared. – Paul Tomblin Jul 02 '15 at 12:10
  • Wow, you are actually trying to detect stack smashing at application level? In any case, I second Paul Tomblin's comment above. – balajeerc Jul 02 '15 at 12:12
  • @Amit: yes, i have set it to zero. – user3425082 Jul 02 '15 at 12:13
  • @Paul Tomblin: I'm taking a course in Coursera, and the Professor comments that the arguments of procedure are pushed into the stack in the reverse order and the variables are pushed in the order they are declared. Do I misunderstand something? – user3425082 Jul 02 '15 at 12:15
  • Than as Paul said, no guarantees, but it looks like your compiler is trying really hard to help you :-) – Amit Jul 02 '15 at 12:15
  • 1
    And as for your latest comment, non of these are "*arguments of a procedure*". These are all local variables. – Amit Jul 02 '15 at 12:16
  • 2
    @user3425082 Arguments could be placed in registers and have nothing to do with the stack. I really don't know why a professor would waste your time with this, except possibly to tell you that overflowing a buffer **may** affect other variables. – PaulMcKenzie Jul 02 '15 at 12:18

1 Answers1

3

Since changing allow via overflow is Undefined Behavior, the compiler might even not have a variable allow at all and change your code to cout << 0 instead when compiling with optimization. This is not a valid way to check for overflow, regardless of where you put allow.

To emphasize: All changes of allow you observe are the result of UB. There are no guarantees on this in the standard what so ever. You can go ahead and speculate on why you see this output today, on you system, with this very toolchain, but the outcome might change to anything (like your program moving your lawn or stealing the crown jewels) for any reason.

Indeed, there is no way to use gets safely. This is why it is removed in both the current C++ and C standard.

You can use std::string and std::getline instead:

string buffer;
std::getline(std::cin, buffer);
Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182