Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 15.04.2013, 00:26   #1
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию Падает релиз, или корявые оптимизации

Рассмотрим два примера:

Код:
Some some;
Some* ptr = &some;
Arg arg= ptr; // all right
Код:
Some some;
Arg arg= &some; //crash visual studio compiler
Во втором примере arg инициализируется временным объектом, которые, как известно - первые претенденты на оптимизацию компилятора для релиз версии.

Компилятор гцц все нормально прожевал. Вижуал студия затупила.
При попытке прочитать данные по адресу релиз-версия падает с исключением.

Если сделать в туловище конструктора отладочный вывод члена, который запоминает получаемый адрес, то все сразу же начинает работать без ошибок.
Видимо, компилятор видит использование адреса, и не трогает его...

Что бы заптетить компилятору оптимизировать аргументы, я сделал их volatile

После этого, компилятор от вижал студии сразу же заработал, и в дебаге и в релизе.

А вот гцц наотрез отказался принимать на входе временные объекты.
То есть, уже нельзя было сделать:

Код:
Arg = 10;
Что категорически не приемлемо.

В итоге, в настоящий момент ситуация разруливается при помощи препроцессора:
для студии аргументы помечены volatile.


Я опасаюсь, что на определенном уровне оптимизации, гцц тоже может оптимизировать аргумент, и его релизная сборка провалится.

Вопрос следующий: как можно запретить компилятору оптимизировать аргументы, так, что бы при этом и студия и гцц могли единообразно работать с временными объектами? Желательно без препроцессора.

Решение должно поддерживать 2003 стандарт, гцц/мингв, компиляторы от вижал студии линейки 2008-2012
_Bers вне форума Ответить с цитированием
Старый 15.04.2013, 09:03   #2
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Кода нет, так что непонятно в чем проблема.
Кстати, учитывайте, что Arg arg=... в gcc вызывает не конструктор а оператор копирования. Попробуйте Arg arg(...)
waleri вне форума Ответить с цитированием
Старый 15.04.2013, 09:26   #3
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Кода нет, так что непонятно в чем проблема.
Кстати, учитывайте, что Arg arg=... в gcc вызывает не конструктор а оператор копирования. Попробуйте Arg arg(...)
1. Основной код не выкладываю, ибо много буковок. Но если суть:


Код:
struct Arg
{

        template<class T> Arg(volatile T& src)
            :mAddr( &src )
        {
             //если разкомментировать, и убрать volatile у аргумента конструктора, то релиз студии падает
             cout<<"addr: "<< mAddr;
        }
        template<class T> Arg(volatile const T& src)
            :mAddr( &src )
        {
             //если разкомментировать, и убрать volatile у аргумента конструктора, то релиз студии падает
             cout<<"addr: "<< mAddr;
        }

        ....

        volatile const void* mAddr;
};
2. Вы не правы. operator= срабатывает только тогда, когда объект уже построен.

Создает объект всегда конструктор.

Код:
Arg arg = 10; //объявление объекта. Работает конструктор
arg = 10; //объект уже построен. Работает operator=

Последний раз редактировалось _Bers; 15.04.2013 в 09:48.
_Bers вне форума Ответить с цитированием
Старый 15.04.2013, 11:08   #4
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Стоп.
В конструкторе Вы берёте адрес переданного (временного) объекта? А Вы уверены, что по стандарту такой код должен работать, логически?
Если это нужно-таки делать именно так, я бы предложил макрос, что-то вроде:
Код:
#define DECLARE_ARG(var, Type, value) Type* temp##__LINE__; Arg var = temp##__LINE__;
Abstraction вне форума Ответить с цитированием
Старый 15.04.2013, 11:40   #5
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

По стандарту
Arg arg = 10
Еквивалентно Arg arg; arg = 10;
MSVC это оптимизирует, gcc обычно нет.

То, чего я не понимаю, это почему вообще чтото падает. Даже если получили адрес а потом объект удалился это никак не мешает, если только не печатаем содержимое по этому адресу и то *после* конструктора (т.е. например в деструкторе). Ну а если делаем это *после* деструктора, тогда странно, почему не падает на gcc. В чем состоится "падение"?

У меня все прекрасно работает (MSVC 2010), правда я все делаю в конструкторе, а в этом случае mAddr вообще не нужна. Наверно все же нужно больше кода.
waleri вне форума Ответить с цитированием
Старый 15.04.2013, 11:43   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
По стандарту
Arg arg = 10
Еквивалентно Arg arg; arg = 10;
MSVC это оптимизирует, gcc обычно нет.

То, чего я не понимаю, это почему вообще чтото падает. Даже если получили адрес а потом объект удалился это никак не мешает, если только не печатаем содержимое по этому адресу и то *после* конструктора (т.е. например в деструкторе). Ну а если делаем это *после* деструктора, тогда странно, почему не падает на gcc. В чем состоится "падение"?

У меня все прекрасно работает (MSVC 2010), правда я все делаю в конструкторе, а в этом случае mAddr вообще не нужна. Наверно все же нужно больше кода.
Вы ошибаетесь.
По стандарту, конструкторы срабатывают при конструировании объектов.
операторы присваивания - при присваивании уже существующему объекту.

Это касается и гцц, и студии. всех.

Можете проверить на любом компиляторе.
_Bers вне форума Ответить с цитированием
Старый 15.04.2013, 11:49   #7
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Abstraction Посмотреть сообщение
Стоп.
В конструкторе Вы берёте адрес переданного (временного) объекта? А Вы уверены, что по стандарту такой код должен работать, логически?
Если это нужно-таки делать именно так, я бы предложил макрос, что-то вроде:
Код:
#define DECLARE_ARG(var, Type, value) Type* temp##__LINE__; Arg var = temp##__LINE__;
Я наверное заморочился просто про временные объекты.
Уже больше суток на ногах и не вылазию из кода:

Код:
int val=10;
int *ptr = &val;   //<--- берем адрес, и адрес валиден, пока жив val

Some some = ptr; //<--- сохраняем адрес, и адрес-член класса  валиден, пока жив val --1--
Some some = &val; //<--- сохраняем адрес, и адрес-член класса валиден, пока жив val --2--
-

Первый случай работает для обоих компиляторов и в дебаге и в релизе
Второй случай падает на релизе студии.

Но если в туловище конструктора поставить отладочный вывод, то второй случай тоже начинает работать корректно.

Последний раз редактировалось _Bers; 15.04.2013 в 11:53.
_Bers вне форума Ответить с цитированием
Старый 15.04.2013, 12:44   #8
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Цитата:
По стандарту
Arg arg = 10
Еквивалентно Arg arg; arg = 10;
Стандарт 2003, раздел 8.5, пункты 12 и 15 определяют такую конструкцию как copy-initialization. 12.6.1, пункт 1 прямо утверждает, что в такой конструкции вызывается только применимый конструктор, и перегрузка оператора присваивания не должна оказывать эффекта на её результат.
Код:
//Эти три определения эквивалентны:
Arg arg(10);
Arg arg = 10;
Arg arg = Arg(10);
Цитата:
адрес-член класса валиден, пока жив val --2--
Если конструктор Some выглядит так же, как приведённый конструктор Arg, то это не так, насколько я понимаю:
Код:
Some<int*> some(&val);//Вызвано Some(int*& src), src есть ссылка на временный объект. Адрес src гарантировано корректен максимум в пределах текущего выражения
Abstraction вне форума Ответить с цитированием
Старый 15.04.2013, 13:52   #9
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от Abstraction Посмотреть сообщение
Если конструктор Some выглядит так же, как приведённый конструктор Arg, то это не так, насколько я понимаю:
Код:
Some<int*> some(&val);//Вызвано Some(int*& src), src есть ссылка на временный объект. Адрес src гарантировано корректен максимум в пределах текущего выражения
Хм.... гм гм гм....

Погоди минуточку....

Ты хочешь сказать, что данный код не корректен:
http://liveworkspace.org/code/4wkRjx$7

То есть, то, что он работает, это чистое везение?

Последний раз редактировалось _Bers; 15.04.2013 в 13:54.
_Bers вне форума Ответить с цитированием
Старый 15.04.2013, 14:31   #10
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
То есть, то, что он работает, это чистое везение?
Да, данный код некорректен. Не зря его GCC не берет.

Далее, ваш код позволяет из const объекта сделать не-const, что тоже не очень хорошо.
waleri вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
релиз собирается дебаг нет. veshiyoleg Visual C++ 2 07.10.2011 20:12
Релиз программы! Нужен совет. DimOn4Ik Свободное общение 4 25.06.2010 13:19
Посоветуйте релиз TreeView KWN, lnc Общие вопросы Delphi 4 12.05.2009 02:55
Релиз ViceCity Манжосов Денис :) Gamedev - cоздание игр: Unity, OpenGL, DirectX 13 05.02.2008 14:18