dedsec_29's blog

By dedsec_29, history, 22 months ago, In English

Today while solving Sereja and Brackets I faced something strange and unexpected.
First I submitted my code in C++20. Submission: https://codeforces.com/contest/380/submission/165753528 (WA) This gave me WA verdict. Then I submitted the exact same code with C++14. Submission: https://codeforces.com/contest/380/submission/165754010 (AC)

I am puzzled why exact identical code give me different verdicts. I also compiled my code with many flags to catch common possible errors, but I got none locally and on custom invocation. Can somebody tell what exactly is causing this difference in verdict?

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

»
22 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

Looks like a compiler bug in -O3 to me. Compare 165769461 and 165769473.

UPD: Not a compiler bug, see dedsec_29's response and my comment below.

  • »
    »
    22 months ago, # ^ |
      Vote: I like it +1 Vote: I do not like it

    nor pointed out that in my parameterized constructor 'Data(char c)', variables anso and ansc are left uninitialized. This probably is the reason for the difference in the verdicts. Please share your builds having flags and sanitizers so that I can catch such mistakes if you have one; shall prove very helpful!

»
22 months ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

It's not a compiler bug, if you run this with undefined sanitizer (-fsanitize=undefined) it shows a left shift on a negative value (on the first line of the combine function)

  • »
    »
    22 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Great catch! Unfortunately, replacing shifts with arithmetical operations does not help: 165773997

»
22 months ago, # |
  Vote: I like it +13 Vote: I do not like it

KAN has noticed that your Data(char c) constructor does not initialize fields. They're read from afterwards, though, which is UB. See 165775020

Hence, not a compiler bug. My recommendation is to always initialize all fields:

struct Data {
    long long ans = 0, cnto = 0, cntc = 0, anso = 0, ansc = 0;
 
    Data() {}
 
    Data(char c) {
        cnto = (c == '(');
        cntc = (c == ')');
    }
 
    Data(long long ans_,long long o_,long long c_,long long anso_,long long ansc_) {
        ans = ans_;
        cnto = o_;
        cntc = c_;
        anso = anso_;
        ansc = ansc_;
    }
};
  • »
    »
    22 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    A good takeaway to always if possible initialize fields even outside constructors! Thank you yeputons