почему так?

Тема в разделе "LANGS.C", создана пользователем sn0w, 27 июн 2019.

  1. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    958
    есть код:
    Код (C++):
    1. struct T
    2. {
    3.      void *payload[128];
    4.      ~T(){}
    5.      T(){}
    6.      // T(T const&){}
    7. };
    8.  
    9. void pass_arg(T arg0)
    10. {
    11.      arg0.payload[0]=(void*)64;
    12. }
    13.  
    14. void foo()
    15. {
    16.     pass_arg(T());
    17. }
    сравнивал gcc, clang, icc, msc (все последних версий, что доступны на godbolt, без оптимизаций итд); у всех всё адекватно, кроме msc, как всегда:
    1) stack_alloc sizeof T (foo)
    2) CTOR (foo)
    3) pass_arg(addrof stack_alloc);...(pass_arg code) ...;ret;
    4) DTOR (foo)
    5) stack_dealloc (foo)

    у первых троих всё вроде норм и одинаково: вызывающий выделяет стековую память, вызывает конструктор на выделенной памяти, передаёт поинтером указатель в pass_arg, там выполняется код, возврат, опять же - вызывающий вызывает деструктор и затем деаллокация.

    у msc же откудато берётся дублирующий обьект, какбудто это copy-initialization from value, и соответственно ситуация исполняется в таком порядке:
    выделение памяти sizeof T * 2, конструктор, копия памяти, обработанной конструктором, во второй блок (по сути - вызов конструктора для 2го обьекта) - передача в test_arg также указателем.

    перед выходом из test_arg - деструктор вот этого темпового, что неявно проинициализировался просто копией, возврат в foo, и деструктор соответсна исходного.

    так вот - откуда у msc второй обьект взялся?

    ключи на всяк
    /std:c++17 /Od /EHs-c- /Ob0 /Oy- /GS- /GR-

    -std=c++17 -O0 -m32 -fno-rtti -fno-exceptions -fno-stack-protector

    ***ПС: если копирующий конструктор раскомментить, то дополнительного объекта msc не создаёт.
     
    Последнее редактирование: 27 июн 2019
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.330
    есть такое понятние, как copy elision, возможно связанно с этим... но да, msc - гуано-компиль...
     
    sn0w нравится это.
  3. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    958
    дадада, именно о copyelision я и замутил тему. с 17 стандарта вроде как - это изменения в ядре в принципе
     
  4. CurryHowardIsomorphism

    CurryHowardIsomorphism Member

    Публикаций:
    0
    Регистрация:
    13 май 2017
    Сообщения:
    97
    Похоже, MSVC считает, что если конструктор копирования тривиален, то можно копировать объект сколько угодно и вызывать деструктор только 1 раз, даже если деструктор не тривиален.
    Но это, конечно, баг. Стандарт даёт право копировать объекты несмотря на т.н. обязательное copy elision если тривиальны конструкторы копирования, перемещения и деструктор https://timsong-cpp.github.io/cppwp/n4659/class.temporary#3
     
    Последнее редактирование: 30 июн 2019
  5. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    958
    msc вообще последнее время создаёт впечатление о своей команде разработчиков, самое яркое что помню - это невызов конструктора базового класса через brace-init-list в constructor-member-initializers-list, я тогда(год назад) отрепортил, так мне сказали что я гражданин и ничего не смыслю, а затем - что да мы в курсе этой проблемы, пофиксим, но вы всё равно - *** и с этого момента обнова вышла аж через 2 месяца.