yeputons's blog

By yeputons, history, 3 years ago, In English

I've bumped into this blog post by imtiyazrasool92 (unfortunately, it's already deleted due to downvotes). They've found out that simply declaring a global variable called read makes your program behave strangely on Codeforces: the outcome of 130645392 is RUNTIME_ERROR, Exit code is 2147483647, and here is the code:

#include <iostream>
int read;
int main(){
    std::ios_base::sync_with_stdio(false);
    std::cin >> read;
}

I was unable to minimize the example any further.

The original post was even more interesting: 130642683 is Accepted, but 130643108 is Runtime Error all of a sudden.

The compiler on Codeforces is G++17 9.2.0 (64 bit, msys2). However, I was able to reproduce the issue both on my local machine (g++ (Rev2, Built by MSYS2 project) 10.3.0) and the latest GCC on Godbolt as long as the -static key is used for compilation just like on Codeforces. Clang is also affected.

It looks like the read variable here replaces the standard Linux read function (which is emulated by msys2). Here is a symmetrical example:

#include <iostream>
int write;
int main(){
    std::ios_base::sync_with_stdio(false);
    std::cout << 10;
}

And here is one more (130646314), although now I at least get some warnings:

int malloc;
int main(){
}
a.cpp:1:5: warning: built-in function 'malloc' declared as non-function [-Wbuiltin-declaration-mismatch]
    1 | int malloc;
      |     ^~~~~~

My understanding is that all these examples invoke ODR violation, which makes the program ill-formed (invalid) without any requirements on the compiler to emit the error. However, I am not sure, so I asked on StackOverflow.

Any other ideas?

  • Vote: I like it
  • +87
  • Vote: I do not like it

»
3 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by yeputons (previous revision, new revision, compare).

»
3 years ago, # |
  Vote: I like it +109 Vote: I do not like it

First of all I want to say that my head hurts from the amount of disrespect you got on StackOverflow.

I may be wrong, but I think it has to do with how the linking process works and especially the -static flag. Without the flag, the c runtime (CRT) which contains definitions of symbols such as read (a function) will be linked dynamically i.e. loaded when you run the executable. If you link the CRT statically, as with any library, the linker will only use definitions from the library for symbols declared, but not defined in the executable — such as read. However, since you defined read as a global variable of type int, it will be skipped in the linking step, so when you ultimately call read from cin>>..., it will try to call it, but it's not a function, thus crashing.

  • »
    »
    3 years ago, # ^ |
      Vote: I like it +171 Vote: I do not like it

    • »
      »
      »
      3 years ago, # ^ |
        Vote: I like it 0 Vote: I do not like it

      The fact that the accepted answer is by someone named "BetterThanYou" makes this so much funnier.

»
3 years ago, # |
Rev. 3   Vote: I like it 0 Vote: I do not like it

i found out that it gives RTE only if we use variable of read name and add

ios_base::sync_with_stdio(false);

this line in code. without this line it works fine

Submission with this line : 130651006 Submission without this line : 130650894

»
3 years ago, # |
  Vote: I like it +10 Vote: I do not like it

I've been using a global function called read() in my template for years...

  • »
    »
    3 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    I use a read() function as well (it's in my fastio template), but I believe that's actually fine, because the problem seems to exist with read(int fd, void *buf, size_t count) (link), and C++ can differentiate between those two functions.

    However it cannot have a variable with the same name as a function and know which one to call, so that's probably why it fails (or maybe because it's a runtime error and functions are really just pointers, it might be trying to call a function thinking that int read is a pointer to something). Either way, a function read() won't cause problems.

»
3 years ago, # |
  Vote: I like it 0 Vote: I do not like it

I mean the KGB won't come arrest you if you define a global variable named "read" so it must be legal.