Re[2]: Гипотеза
От: Lorenzo_LAMAS  
Дата: 02.10.06 10:24
Оценка:
Лучше почитать пропозал Стивена Адамчука, где он говорит о разрушении временных объектов.
Of course, the code must be complete enough to compile and link.
Re[3]: Гипотеза
От: remark Россия http://www.1024cores.net/
Дата: 02.10.06 11:06
Оценка: +1 :)
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Лучше почитать пропозал Стивена Адамчука, где он говорит о разрушении временных объектов.


Как только кинешь ссылочку, так сразу
А чем лучше-то? Это ж пропозал. Нам ещё как минимум несколько лет работать с существующими средствами. Баги от чтения пропозала не исчезнут


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Гипотеза
От: elcste  
Дата: 02.10.06 14:58
Оценка: 8 (1)
Здравствуйте, remark, Вы писали:

R>Как только кинешь ссылочку, так сразу


WG21/N1286
Re[3]: Гипотеза
От: remark Россия http://www.1024cores.net/
Дата: 02.10.06 15:17
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>Лучше почитать пропозал Стивена Адамчука, где он говорит о разрушении временных объектов.


Не в кассу. Там о разрушении параметров.


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Гипотеза
От: Lorenzo_LAMAS  
Дата: 03.10.06 09:18
Оценка:
я не очень внимательно читал твой пример, и не очень хорошо помню о чем говорил Стивен, но как раз разрушение временных объектов там хорошо и доходчиво (ИМХО) объяснялось.
Of course, the code must be complete enough to compile and link.
Re[5]: Гипотеза
От: Lorenzo_LAMAS  
Дата: 03.10.06 09:20
Оценка:
там вон даже пункт у него есть Is it a Parameter or a Temporary?
Of course, the code must be complete enough to compile and link.
Re: Жёсткий БАГ MSVC7.1 и 8 тоже
От: Кодт Россия  
Дата: 03.10.06 10:01
Оценка: 14 (2)
Здравствуйте, remark, Вы писали:

R>Вот минимальный код, приводящий к ошибке:


Написал эквивалентный код, чтобы не тащить лишнее (т.е. shared_ptr).
#include <iostream>
using std::cout;
using std::endl;

int refcount = 0;

struct share
{
    share()
    {
        ++refcount;
        cout << this << " : " << __FUNCTION__ << " : " << refcount << endl;
    }
    share(const share&)
    {
        ++refcount;
        cout << this << " : " << __FUNCTION__ << " : " << refcount << endl;
    }
    ~share()
    {
        --refcount;
        cout << this << " : " << __FUNCTION__ << " : " << refcount << endl;
    }

    int get() const
    {
        cout << this << " : " << __FUNCTION__ << " : " << refcount << endl;
        return 0;
    }
};

share make()
{
    cout << __FUNCTION__ << " : " << refcount << endl;
    return share();
}

int unfold(share tmp)
{
    cout << __FUNCTION__ << " : " << refcount << endl;
    return tmp.get();
}

void accept(int)
{
    cout << __FUNCTION__ << " : " << refcount << endl;
}


int main()
{
    cout << __FUNCTION__ << " : " << refcount << endl;
    accept(unfold(make()));
    cout << __FUNCTION__ << " : " << refcount << endl;
    return 0;
}

Проверил на VC8. Та же фигня. Причём и в релизе, и в дебаге (где, казалось бы, оптимизации отключены).
main : 0
make : 0                       -- ещё нет объектов...
0012FE84 : share::share : 1    -- вот мы его создали в make() - return share()
unfold : 1                     -- вот он уже как параметр unfold
0012FE84 : share::get : 1      -- пока что жив...
0012FE84 : share::~share : 0   -- вот мы вышли из unfold
accept : 0                     -- и к моменту входа в accept все умерли
main : 0
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[6]: Гипотеза
От: remark Россия http://www.1024cores.net/
Дата: 03.10.06 10:02
Оценка:
Здравствуйте, Lorenzo_LAMAS, Вы писали:

L_L>там вон даже пункт у него есть Is it a Parameter or a Temporary?


Я там пробежался по быстрому. Имхо ничего нового к этому вопросу пропозал не добавляет.
В разделе Is it a Parameter or a Temporary? Только ещё раз говорится, что временные объекты должны жить до точки с запятой. Это собственно я ещё в первом посте написал. Больше ничего интересного по этому вопросу я не вижу.
Он там вроде в основном говорит о том, когда должны разрушаться временные объекты, которые были созданы при инициализации параметров функции.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: Гипотеза
От: elcste  
Дата: 03.10.06 11:06
Оценка: 8 (1)
Здравствуйте, remark, Вы писали:

R>Я там пробежался по быстрому. Имхо ничего нового к этому вопросу пропозал не добавляет.


Текст Адамчика отчасти объясняет причины ошибки, допущенной разработчиками MSVC, — следование 5.2.2/4

The lifetime of a parameter ends when the function in which it is defined returns.

при игнорировании 12.8/15

In such cases, the implementation treats the source and target of the omitted copy operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization.

Re[2]: Жёсткий БАГ MSVC7.1 и 8 тоже
От: night beast СССР  
Дата: 03.10.06 14:29
Оценка:
Здравствуйте, Кодт, Вы писали:

R>>Вот минимальный код, приводящий к ошибке:


К>Написал эквивалентный код, чтобы не тащить лишнее (т.е. shared_ptr).


а если по ссылке передавать, то тоже не работает?
может из-за RVO гонит.
Re[3]: Жёсткий БАГ MSVC7.1 и 8 тоже
От: remark Россия http://www.1024cores.net/
Дата: 03.10.06 14:39
Оценка:
Здравствуйте, night beast, Вы писали:

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


R>>>Вот минимальный код, приводящий к ошибке:


К>>Написал эквивалентный код, чтобы не тащить лишнее (т.е. shared_ptr).


NB>а если по ссылке передавать, то тоже не работает?

NB>может из-за RVO гонит.

Если по ссылке, то должно работать.
здесь
Автор: remark
Дата: 02.10.06
я писал. Я так понял, что проявляется только когда "внутренняя" функция возвращает по значению, а "внешняя" принимает по значению. Т.е. компилятор совмещает эти объекты.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Жёсткий БАГ MSVC7.1 и 8 тоже
От: night beast СССР  
Дата: 03.10.06 14:46
Оценка:
Здравствуйте, remark, Вы писали:

R>>>>Вот минимальный код, приводящий к ошибке:


К>>>Написал эквивалентный код, чтобы не тащить лишнее (т.е. shared_ptr).


NB>>а если по ссылке передавать, то тоже не работает?

NB>>может из-за RVO гонит.

R>Если по ссылке, то должно работать.


так должно или работает? (нет копилятора под рукой)

R>здесь
Автор: remark
Дата: 02.10.06
я писал. Я так понял, что проявляется только когда "внутренняя" функция возвращает по значению, а "внешняя" принимает по значению. Т.е. компилятор совмещает эти объекты.


RVO
Re[4]: Жёсткий БАГ MSVC7.1 и 8 тоже
От: night beast СССР  
Дата: 04.10.06 05:56
Оценка:
R>>>>Вот минимальный код, приводящий к ошибке:

К>>>Написал эквивалентный код, чтобы не тащить лишнее (т.е. shared_ptr).


NB>>а если по ссылке передавать, то тоже не работает?

NB>>может из-за RVO гонит.

R>Если по ссылке, то должно работать.


работает.

R>здесь
Автор: remark
Дата: 02.10.06
я писал. Я так понял, что проявляется только когда "внутренняя" функция возвращает по значению, а "внешняя" принимает по значению. Т.е. компилятор совмещает эти объекты.


в мелкософт написал?
ве таки неприятный баг. вляпаешься -- фиг найдешь.

PS: гсс продолжает рулить
Re[3]: Жёсткий БАГ MSVC7.1 и 8 тоже
От: Кодт Россия  
Дата: 04.10.06 08:31
Оценка: 32 (5) :)
Здравствуйте, night beast, Вы писали:

NB>может из-за RVO гонит.


Это не RVO, а криво сделанная оптимизация копирования. Проверяем.
#include <iostream>
using namespace std;

struct Data
{
    int m_refcount;
    unsigned m_signature;
    Data() : m_refcount(0), m_signature(0x900DDA7A) { cout<<"CONSTRUCT"<<endl; }
    ~Data() { cout<<"DESTROY"<<endl; m_signature=0xDEADFACE; }
    void addref() { ++m_refcount; }
    void release() { if(--m_refcount==0) delete this; }
};
ostream& operator<<(ostream& ost, const Data& data)
{
    return ost<<"Data"<<"(ref="<<data.m_refcount<<",sig="<<hex<<data.m_signature<<dec<<")";
}

struct Ptr;
ostream& operator<<(ostream& ost, const Ptr& );

static int ids = 0;
struct Ptr
{
    int m_id; // to see lifetime of particular Ptrs
    Data* m_data;
    explicit Ptr(Data* data) : m_id(++ids), m_data(data)
    {
        m_data->addref();
        cout<<"ctor "<<*this<<endl;
    }
    Ptr(const Ptr& src) : m_id(++ids), m_data(src.m_data)
    {
        m_data->addref();
        cout<<"cctor "<<*this<<endl;
    }
    ~Ptr()
    {
        cout<<"dtor "<<*this<<endl;
        m_data->release();
    }
    
    Data* get() const
    {
        cout<<"get "<<*this<<endl;
        return m_data;
    }
};
ostream& operator<<(ostream& ost, const Ptr& ptr)
{
    return ost<<"Ptr #"<<ptr.m_id<<" ("<<*ptr.m_data<<")";
}

void accept(Data* data)
{
    cout<<"accept "<<*data<<endl;
}

Data* pass(Ptr ptr)
{
    cout<<"pass ("<<ptr<<")"<<endl;
    return ptr.get();
}

Ptr rvo_make()
{
    cout<<"rvo_make"<<endl;
    return Ptr(new Data());
}

Ptr nrvo_make()
{
    cout<<"nrvo_make"<<endl;
    Ptr ptr(new Data());
    cout<<"nrvo_make completed"<<endl;
    return ptr;
}

Ptr nonopt_make()
{
    cout<<"nonopt_make"<<endl;
    if(rand() % 2)
    {
        Ptr ptr(new Data());
        cout<<"nonopt_make completed, v1"<<endl;
        return ptr;
    }
    else
    {
        Ptr ptr(new Data());
        cout<<"nonopt_make completed, v2"<<endl;
        return ptr;
    }
}

int main()
{
    cout<<"---tmp---"<<endl;
    ids=0;
    accept(pass(Ptr(new Data())));
    
    cout<<"---rvo---"<<endl;
    ids=0;
    accept(pass(rvo_make()));
    
    cout<<"---nrvo---"<<endl;
    ids=0;
    accept(pass(nrvo_make()));
    
    cout<<"---nonopt---"<<endl;
    ids=0;
    accept(pass(nonopt_make()));
}


Получаем (VC8)
Действиеdebugrelease
TMP
CONSTRUCT
ctor Ptr #1 (Data(ref=1,sig=900dda7a))
pass (Ptr #1 (Data(ref=1,sig=900dda7a)))
get Ptr #1 (Data(ref=1,sig=900dda7a))
dtor Ptr #1 (Data(ref=1,sig=900dda7a))
DESTROY
accept Data(ref=3473816,sig=3530c0)

CONSTRUCT
ctor Ptr #1 (Data(ref=1,sig=900dda7a))
pass (Ptr #1 (Data(ref=1,sig=900dda7a)))
get Ptr #1 (Data(ref=1,sig=900dda7a))
dtor Ptr #1 (Data(ref=1,sig=900dda7a))
DESTROY
accept Data(ref=3473816,sig=3530c0)
RVO
rvo_make
CONSTRUCT
ctor Ptr #1 (Data(ref=1,sig=900dda7a))
pass (Ptr #1 (Data(ref=1,sig=900dda7a)))
get Ptr #1 (Data(ref=1,sig=900dda7a))
dtor Ptr #1 (Data(ref=1,sig=900dda7a))
DESTROY
accept Data(ref=3473816,sig=355050)

rvo_make
CONSTRUCT
ctor Ptr #1 (Data(ref=1,sig=900dda7a))
pass (Ptr #1 (Data(ref=1,sig=900dda7a)))
get Ptr #1 (Data(ref=1,sig=900dda7a))
dtor Ptr #1 (Data(ref=1,sig=900dda7a))
DESTROY
accept Data(ref=3473816,sig=355050)
NRVO
nrvo_make
CONSTRUCT
ctor Ptr #1 (Data(ref=1,sig=900dda7a))
nrvo_make completed
cctor Ptr #2 (Data(ref=2,sig=900dda7a))
dtor Ptr #1 (Data(ref=2,sig=900dda7a))
pass (Ptr #2 (Data(ref=1,sig=900dda7a)))
get Ptr #2 (Data(ref=1,sig=900dda7a))
dtor Ptr #2 (Data(ref=1,sig=900dda7a))
DESTROY
accept Data(ref=3473816,sig=355050)

nrvo_make
CONSTRUCT
ctor Ptr #1 (Data(ref=1,sig=900dda7a))
nrvo_make completed
pass (Ptr #1 (Data(ref=1,sig=900dda7a)))
get Ptr #1 (Data(ref=1,sig=900dda7a))
dtor Ptr #1 (Data(ref=1,sig=900dda7a))
DESTROY
accept Data(ref=3473816,sig=3530c0)
NonOpt
nonopt_make
CONSTRUCT
ctor Ptr #1 (Data(ref=1,sig=900dda7a))
nonopt_make completed, v1
cctor Ptr #2 (Data(ref=2,sig=900dda7a))
dtor Ptr #1 (Data(ref=2,sig=900dda7a))
pass (Ptr #2 (Data(ref=1,sig=900dda7a)))
get Ptr #2 (Data(ref=1,sig=900dda7a))
dtor Ptr #2 (Data(ref=1,sig=900dda7a))
DESTROY
accept Data(ref=3473816,sig=355050)

nonopt_make
CONSTRUCT
ctor Ptr #1 (Data(ref=1,sig=900dda7a))
nonopt_make completed, v1
cctor Ptr #2 (Data(ref=2,sig=900dda7a))
dtor Ptr #1 (Data(ref=2,sig=900dda7a))
pass (Ptr #2 (Data(ref=1,sig=900dda7a)))
get Ptr #2 (Data(ref=1,sig=900dda7a))
dtor Ptr #2 (Data(ref=1,sig=900dda7a))
DESTROY
accept Data(ref=3473816,sig=355050)
Видно, что в дебажной версии NRVO не выполняется.
Однако вне зависимости от RVO/NRVO мы получаем расстройство памяти.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[5]: Жёсткий БАГ MSVC7.1 и 8 тоже
От: Кодт Россия  
Дата: 04.10.06 09:31
Оценка: +1
Здравствуйте, night beast, Вы писали:

NB>в мелкософт написал?

NB>ве таки неприятный баг. вляпаешься -- фиг найдешь.

Причём должен рваться не только на shared_ptr, но и на CComPtr.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[6]: Жёсткий БАГ MSVC7.1 и 8 тоже
От: remark Россия http://www.1024cores.net/
Дата: 04.10.06 09:56
Оценка:
Здравствуйте, Кодт, Вы писали:

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


NB>>в мелкософт написал?

NB>>ве таки неприятный баг. вляпаешься -- фиг найдешь.

К>Причём должен рваться не только на shared_ptr, но и на CComPtr.


С любым классом, который использует разделяемое тело.
Есть пример гораздо ближе — их любимый CString



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Жёсткий БАГ MSVC7.1
От: Вадим Никулин Россия Здесь
Дата: 06.10.06 05:17
Оценка:
Здравствуйте, remark, Вы писали:

R>И на что, скажите, надеяться в этой жизни???


R>


К слову, вот, что Como Выводит:

main
getAAAPtr
AAA
getAAA
aaa
deleterAAA
~AAA
Re[4]: Жёсткий БАГ MSVC7.1 и 8 тоже
От: Ovl Россия  
Дата: 06.10.06 09:25
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Ptr nonopt_make()

К>{
К> cout<<"nonopt_make"<<endl;
К> if(rand() % 2)
К> {
К> Ptr ptr(new Data());
К> cout<<"nonopt_make completed, v1"<<endl;
К> return ptr;
К> }
К> else
К> {
К> Ptr ptr(new Data());
К> cout<<"nonopt_make completed, v2"<<endl;
К> return ptr;
К> }
К>}

может для полноты ощущения вместо rand() использовать volatile?
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
Re[5]: Жёсткий БАГ MSVC7.1 и 8 тоже
От: Кодт Россия  
Дата: 06.10.06 11:04
Оценка: 1 (1)
Здравствуйте, Ovl, Вы писали:

Ovl>может для полноты ощущения вместо rand() использовать volatile?


Да без разницы — мне просто хотелось помешать компилятору.
Кстати, здесь всё равно есть возможности для NRVO, поскольку в каждой ветке ровно один объект.
А вот такой способ гарантирует невозможность NRVO
Ptr* volatile p;
Ptr nonopt_make()
{
    Ptr ptr(new Data());
    p = &ptr;
    return *p;
}
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[5]: Сообщил в мелкософт
От: remark Россия http://www.1024cores.net/
Дата: 08.10.06 10:52
Оценка: 37 (2)
Здравствуйте, night beast, Вы писали:

NB>в мелкософт написал?

NB>ве таки неприятный баг. вляпаешься -- фиг найдешь.

здесь (кстати, можете голосовать, оценивать и комментировать )

Проверил на MSVC8.0SP1 та же фигня

Если чо интересное ответят, то сообщу.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.