Блог пользователя dedsec_29

Автор dedsec_29, история, 22 месяца назад, По-английски

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?

  • Проголосовать: нравится
  • +13
  • Проголосовать: не нравится

»
22 месяца назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

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 месяца назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится

    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 месяца назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

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 месяца назад, # |
  Проголосовать: нравится +13 Проголосовать: не нравится

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 месяца назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

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