Неправильная кодогенерация, MSVC 2017
От: johny5 Новая Зеландия
Дата: 11.03.20 11:03
Оценка: 13 (2)
Только что обнаружил, решил похвалиться — MSVC 2017 Community 15.9.21 и ниже создаёт бешенный мемори лик в релизе/х64 с таким кодом. В дебаге код корректный. В 2015й этот же код работал.


#include <iostream>
#include <vector>

class Battle
{
public:
    Battle() 
    {
        arr.reserve(100000);
    }

    std::vector<char> arr;
};

struct BattleArchiveAnswerMsg
{
    int            party_id = -1;
    Battle        battle;
};

volatile bool something = false;

BattleArchiveAnswerMsg  get_battles(int player_id)
{
    if(something)
    {
        return {};
    }


    BattleArchiveAnswerMsg  bansw;
    bansw.party_id = 1;

    if(something)
    {
        bansw.battle = Battle();

        return bansw;
    }

    return {};
}


int main()
{
    std::cout << "Hello World!\n"; 

    while(true)
        get_battles(32);
}


Деструктор ~Battle объекта в bansw не вызывается в конце функции и память течёт.

Подал им багрепорт.
Отредактировано 11.03.2020 11:34 johny5 . Предыдущая версия .
visual studio bug
Re: Неправильная кодогенерация, MSVC 2017
От: okman Беларусь https://searchinform.ru/
Дата: 11.03.20 13:24
Оценка:
Здравствуйте, johny5, Вы писали:

J>...


Спасибо, любопытно (и очень злободневно — мы как раз переходим на VS2017)...
Проверил у себя — действительно, на Release | x64 потребление памяти растет очень быстро, а в Debug такого не наблюдается.
VS2017 15.9.21.

J>Подал им багрепорт.


А ссылкой не поделитесь? Я бы свой голос тоже оставил...
Re[2]: Неправильная кодогенерация, MSVC 2017
От: AndrewJD США  
Дата: 11.03.20 15:53
Оценка: +1
Здравствуйте, okman, Вы писали:

O>мы как раз переходим на VS2017...

А почему не VS2019 ?
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re[2]: Неправильная кодогенерация, MSVC 2017
От: K13 http://akvis.com
Дата: 11.03.20 17:40
Оценка: 6 (1)
O>Спасибо, любопытно (и очень злободневно — мы как раз переходим на VS2017)...
O>Проверил у себя — действительно, на Release | x64 потребление памяти растет очень быстро, а в Debug такого не наблюдается.
O>VS2017 15.9.21.

VS2019 16.5 Preview 3.0 -- потребление памяти не растет
Re[2]: Неправильная кодогенерация, MSVC 2017
От: johny5 Новая Зеландия
Дата: 11.03.20 19:39
Оценка:
Здравствуйте, okman, Вы писали:

O>Здравствуйте, johny5, Вы писали:


J>>...


O>Спасибо, любопытно (и очень злободневно — мы как раз переходим на VS2017)...

O>Проверил у себя — действительно, на Release | x64 потребление памяти растет очень быстро, а в Debug такого не наблюдается.
O>VS2017 15.9.21.

J>>Подал им багрепорт.


O>А ссылкой не поделитесь? Я бы свой голос тоже оставил...


https://developercommunity.visualstudio.com/content/problem/945527/incorrect-code-generation-missing-destructor-call.html

Подавал через форму в VS, в вебе еле нашёл. В вебе форматирование съехавшее. Попробую поправить.
Re[3]: Неправильная кодогенерация, MSVC 2017
От: okman Беларусь https://searchinform.ru/
Дата: 12.03.20 07:46
Оценка:
Здравствуйте, AndrewJD, Вы писали:

O>>мы как раз переходим на VS2017...

AJD>А почему не VS2019 ?

Пока будем переходить на VS2019, выйдет VS2021 и кто-то вновь будет спрашивать, почему не VS2021

А если серьезно — очень много кода и различных других аспектов, которые плохо "переносят" переезд на новые версии Visual Studio.
Очень тяжело было переходить с VS2008, т.к. другие страницы свойств, другой формат проектных файлов и еще много всего.
VS2017 нравится в плане стабильности, потому что новые фичи в нее уже не добавляют, а только багфиксы.
Но после VS2017, надеюсь, вскоре перейдем и на VS2019.
Re[4]: Неправильная кодогенерация, MSVC 2017
От: SaZ  
Дата: 12.03.20 10:25
Оценка:
Здравствуйте, okman, Вы писали:

O>...

O>А если серьезно — очень много кода и различных других аспектов, которые плохо "переносят" переезд на новые версии Visual Studio.

Так вроде же с 2015 они гарантируют совместимость ABI. Т.е. если у вас есть совсем экзотика, которая собирается только 2015 студией, вы можете использовать соответствующий тулчейн и всё будет ок, даже при мешанине с более новыми версиями.
Re[3]: Неправильная кодогенерация, MSVC 2017
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 13.03.20 07:48
Оценка:
Здравствуйте, AndrewJD, Вы писали:

AJD>Здравствуйте, okman, Вы писали:


O>>мы как раз переходим на VS2017...

AJD>А почему не VS2019 ?

Cижу на 2019. Официально поддерживаю еще 2017 (выкладываю сборки, но плотно не тестирую). Втихоря собираю еще на 2015 и 2013.

Вот сегодня попытался один проект пересобрать в 2013 и вылезла ошибка компиляции (сегодняшний день, походу, идет фтопку).

В 2015, 2017, 2019 (включая последней preview) компилируют без проблем.

  Тест для репорта о баге(?)
//////////////////////////////////////////////////////////////////////////////

class TClass1
{
 public:
  class tag_InnerClass;
};

//////////////////////////////////////////////////////////////////////////////

class TClass1::tag_InnerClass
{
 public:
  tag_InnerClass();
};

//////////////////////////////////////////////////////////////////////////////

TClass1::tag_InnerClass::tag_InnerClass::tag_InnerClass::tag_InnerClass()
{
}

//////////////////////////////////////////////////////////////////////////////

void main()
{
}

//////////////////////////////////////////////////////////////////////////////

Так что, оно, конечно, хочется ломиться вперед и выкинуть все старье.

Но пятая точка говорит — не стоит
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Неправильная кодогенерация, MSVC 2017
От: _NN_ www.nemerleweb.com
Дата: 13.03.20 15:37
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

Для начала int main, но это издержки совместимости в MSVC.
А так и GCC и Clang довольны кодом

https://gcc.godbolt.org/z/mBmEEC
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Неправильная кодогенерация, MSVC 2017
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 13.03.20 16:51
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Для начала int main, но это издержки совместимости в MSVC.


Сорян, сэкономил

_NN>А так и GCC и Clang довольны кодом


_NN>https://gcc.godbolt.org/z/mBmEEC


Это как, разрешено законом что-ли?

В чем прикол такое компилировать?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[6]: Неправильная кодогенерация, MSVC 2017
От: _NN_ www.nemerleweb.com
Дата: 14.03.20 15:20
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, _NN_, Вы писали:


_NN>>Для начала int main, но это издержки совместимости в MSVC.


КД>Сорян, сэкономил

Как раз int это экономия, а void лишний символ.

_NN>>А так и GCC и Clang довольны кодом


_NN>>https://gcc.godbolt.org/z/mBmEEC


КД>Это как, разрешено законом что-ли?


КД>В чем прикол такое компилировать?


Хороший вопрос. Не имею понятия, но можно и покруче:

struct A { struct B { struct C { void f(); }; }; };

void A::A::B::B::C::C::f() {} // Voila :)
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: Неправильная кодогенерация, MSVC 2017
От: night beast СССР  
Дата: 14.03.20 17:05
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

_NN>>А так и GCC и Clang довольны кодом


_NN>>https://gcc.godbolt.org/z/mBmEEC


КД>Это как, разрешено законом что-ли?

КД>В чем прикол такое компилировать?

в чем именно видишь проблему?
Re[7]: Неправильная кодогенерация, MSVC 2017
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 14.03.20 19:43
Оценка:
Здравствуйте, night beast, Вы писали:

_NN>>>А так и GCC и Clang довольны кодом


_NN>>>https://gcc.godbolt.org/z/mBmEEC


КД>>Это как, разрешено законом что-ли?

КД>>В чем прикол такое компилировать?

NB>в чем именно видишь проблему?


А как это можно продать использовать в реальном коде?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[8]: Неправильная кодогенерация, MSVC 2017
От: night beast СССР  
Дата: 15.03.20 06:28
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

_NN>>>>https://gcc.godbolt.org/z/mBmEEC


NB>>в чем именно видишь проблему?


КД>А как это можно продать использовать в реальном коде?


pimpl же.
в хидере в классе мембером указатель.
в cpp -- реализация класса.
Re[9]: Неправильная кодогенерация, MSVC 2017
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 15.03.20 07:57
Оценка:
Здравствуйте, night beast, Вы писали:

NB>>>в чем именно видишь проблему?


КД>>А как это можно продать использовать в реальном коде?


NB>pimpl же.

NB>в хидере в классе мембером указатель.
NB>в cpp -- реализация класса.

Про pimpl я слышал, но причем он тут — не догоняю.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[10]: Неправильная кодогенерация, MSVC 2017
От: night beast СССР  
Дата: 15.03.20 08:07
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

NB>>pimpl же.

NB>>в хидере в классе мембером указатель.
NB>>в cpp -- реализация класса.

КД>Про pimpl я слышал, но причем он тут — не догоняю.


// h
struct Foo
{
Foo();
~Foo();

private:
struct FooImpl;
std::unique_ptr<FooImpl> m_impl;
};

//cpp
struct Foo::FooImpl
{
};

Foo::Foo() : m_impl(make_unique) {}
Foo::~Foo() {}


или вопрос в том что tag_InnerClass несколько раз идет? тогда сорри, не обратил внимание.
Re[5]: Неправильная кодогенерация, MSVC 2017
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 16.03.20 05:26
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Для начала int main, но это издержки совместимости в MSVC.

_NN>А так и GCC и Clang довольны кодом

_NN>https://gcc.godbolt.org/z/mBmEEC


Мелькнула мысль — "кто у кого украл?"
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[6]: Неправильная кодогенерация, MSVC 2017
От: rg45 СССР  
Дата: 17.03.20 06:48
Оценка: 16 (2)
Здравствуйте, Коваленко Дмитрий, Вы писали:

_NN>>https://gcc.godbolt.org/z/mBmEEC


КД>Это как, разрешено законом что-ли?


КД>В чем прикол такое компилировать?


Это называется injected-class-name. Имя класса вставляется в область видимости класса как открытый член-тип. Благодаря этому мы имеем возможность, например, внутри шаблонного класса использовать имя этого шаблонного класса без указания всех его параметров. Это избавляет нас от ненужного многословия при написании конструкторов копирования/перемещения, операторов присваивания п пр. А посколку имя открытое (public) мы имеем к нему доступ и снаружи. Ну и вложенность обращения тоже не запрещается:

http://coliru.stacked-crooked.com/a/87dfa6482e17b06e

static_assert(std::is_same_v<std::tuple<int, char*, double>, typename std::tuple<int, char*, double>::tuple::tuple::tuple::tuple>);


P.S. В некоторых случаях, таких как в моем примере, при обращении к injected-class-name требуется явное использование ключевого слова 'typename', чтобы отличить имя типа от конструктора. В других случаях, там где из контекста понятно, что это имя типа, использовение 'typename' не требуется.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 17.03.2020 7:00 rg45 . Предыдущая версия .
Re[7]: Неправильная кодогенерация, MSVC 2017
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 18.03.20 06:42
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Коваленко Дмитрий, Вы писали:


_NN>>>https://gcc.godbolt.org/z/mBmEEC


КД>>Это как, разрешено законом что-ли?


КД>>В чем прикол такое компилировать?


R>Это называется injected-class-name.


То есть, если говорить прямо — это побочный эффект.

  Я тут еще немного ... пострадал хренью
//////////////////////////////////////////////////////////////////////////////

class TClass1
{
 public:
  typedef TClass1                           self_type;

 public:
  class tag_InnerClass;
  class tag_InnerClass2;
  class tag_InnerClass3;
  class tag_InnerClass4;
};

//////////////////////////////////////////////////////////////////////////////

class TClass1::tag_InnerClass
{
 public:
  tag_InnerClass();
};

//////////////////////////////////////////////////////////////////////////////

TClass1::tag_InnerClass::tag_InnerClass::tag_InnerClass::tag_InnerClass()
{
}

//////////////////////////////////////////////////////////////////////////////

class TClass1::tag_InnerClass2
{
 public:
  tag_InnerClass2();
};

//////////////////////////////////////////////////////////////////////////////

TClass1::TClass1::TClass1::TClass1::tag_InnerClass2::tag_InnerClass2::tag_InnerClass2::tag_InnerClass2()
{
}

//////////////////////////////////////////////////////////////////////////////

class TClass1::tag_InnerClass3
{
 private:
  typedef tag_InnerClass3      self_type;

 public:
  tag_InnerClass3();
};

//////////////////////////////////////////////////////////////////////////////

TClass1::self_type::TClass1::self_type::self_type::tag_InnerClass3::self_type::tag_InnerClass3::self_type::self_type::tag_InnerClass3()
{
}

//////////////////////////////////////////////////////////////////////////////

class TClass1::tag_InnerClass4
{
 private:
  typedef tag_InnerClass4      self_type;

  self_type(const self_type&)=delete;
  self_type& operator = (const self_type&)=delete;

 public:
  self_type::self_type::self_type::self_type::self_type()=default;
  
 //~self_type(); //увы, но нет.
};

//////////////////////////////////////////////////////////////////////////////

int main()
{
 return 0;
}

//////////////////////////////////////////////////////////////////////////////

VS2019 v16.4.6 компилирует без проблем.

А вот тут ругаются на tag_InnerClass4.

PS. Ветку наверное стоит выделить в отдельный топик.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[8]: Неправильная кодогенерация, MSVC 2017
От: rg45 СССР  
Дата: 18.03.20 09:21
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>То есть, если говорить прямо — это побочный эффект.


Наверное, можно и так сказать.

  Я тут еще немного ... пострадал хренью
КД>
КД>//////////////////////////////////////////////////////////////////////////////

КД>class TClass1
КД>{
КД> public:
КД>  typedef TClass1                           self_type;

КД> public:
КД>  class tag_InnerClass;
КД>  class tag_InnerClass2;
КД>  class tag_InnerClass3;
КД>  class tag_InnerClass4;
КД>};

КД>//////////////////////////////////////////////////////////////////////////////

КД>class TClass1::tag_InnerClass
КД>{
КД> public:
КД>  tag_InnerClass();
КД>};

КД>//////////////////////////////////////////////////////////////////////////////

КД>TClass1::tag_InnerClass::tag_InnerClass::tag_InnerClass::tag_InnerClass()
КД>{
КД>}

КД>//////////////////////////////////////////////////////////////////////////////

КД>class TClass1::tag_InnerClass2
КД>{
КД> public:
КД>  tag_InnerClass2();
КД>};

КД>//////////////////////////////////////////////////////////////////////////////

КД>TClass1::TClass1::TClass1::TClass1::tag_InnerClass2::tag_InnerClass2::tag_InnerClass2::tag_InnerClass2()
КД>{
КД>}

КД>//////////////////////////////////////////////////////////////////////////////

КД>class TClass1::tag_InnerClass3
КД>{
КД> private:
КД>  typedef tag_InnerClass3      self_type;

КД> public:
КД>  tag_InnerClass3();
КД>};

КД>//////////////////////////////////////////////////////////////////////////////

КД>TClass1::self_type::TClass1::self_type::self_type::tag_InnerClass3::self_type::tag_InnerClass3::self_type::self_type::tag_InnerClass3()
КД>{
КД>}

КД>//////////////////////////////////////////////////////////////////////////////

КД>class TClass1::tag_InnerClass4
КД>{
КД> private:
КД>  typedef tag_InnerClass4      self_type;

КД>  self_type(const self_type&)=delete;
КД>  self_type& operator = (const self_type&)=delete;

КД> public:
КД>  self_type::self_type::self_type::self_type::self_type()=default;
  
КД> //~self_type(); //увы, но нет.
КД>};

КД>//////////////////////////////////////////////////////////////////////////////

КД>int main()
КД>{
КД> return 0;
КД>}

КД>//////////////////////////////////////////////////////////////////////////////
КД>

КД>VS2019 v16.4.6 компилирует без проблем.

КД>А вот тут ругаются на tag_InnerClass4.


Здесь может иметь значение, что self_type — определенное пользователем имя, все-таки, а не injected class name. Хоть концептуально они и похожи, наверное, могут обрабатываться по разным правилам и с разной степенью строгости.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 18.03.2020 10:01 rg45 . Предыдущая версия . Еще …
Отредактировано 18.03.2020 9:22 rg45 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.