Re[8]: [MSVC] Инициализация членов класса
От: IROV..  
Дата: 18.04.11 17:44
Оценка: +1 -1
Здравствуйте, wander, Вы писали:

IRO>>Для меня UB это запрет, просто трудно уловимый компилятором(поэтому он и не ругаеться).

W>Если на то пошло, то UB там из-за использования ссылки на невалидную память, а не из-за порядка инициализации. Порядок иницализации тут просто поспособствовал этому хорошо.
Ну я именно это и хотел сказать, что дело не в порядке, а вообще в том что мы используем(разыменовываем) неготовый указатель.
я не волшебник, я только учусь!
Re: [MSVC] Инициализация членов класса
От: IROV..  
Дата: 18.04.11 16:23
Оценка: -1
Здравствуйте, Abyx, Вы писали:

A>Как такого избежать?

Писать

: bar(this->foo)

Тогда получишь варнинг
я не волшебник, я только учусь!
Re: [MSVC] Инициализация членов класса
От: Alexander G Украина  
Дата: 20.04.11 10:34
Оценка: :)
Здравствуйте, Abyx, Вы писали:

A>...


A>Как такого избежать?


  • придерживаться Naming convention, который отличает data members от всего остального.

    struct Holder
    {
        Holder()
            : bar_(foo_) // выглядит подозрительно, необходимо проверить конструктор bar_.
            , foo_()
        {}
    
        Bar bar_;
        Foo foo_;
    };


  • стремиться хранить по указателю любые нетривиальные классы. это полезно ещё тем, что позволяет избежать лишних зависимостей (как в pimpl).

    struct Holder
    {
        Holder();
        scoped_ptr<Bar> bar_;
        scoped_ptr<Foo> foo_;
    };
    
    Holder::Holder()
    {
        bar_.reset(new Bar(*foo_)); // ошибка очевидна.
        foo_.reset(new Foo()); 
    }
  • Русский военный корабль идёт ко дну!
    [MSVC] Инициализация членов класса
    От: Abyx Россия  
    Дата: 18.04.11 16:06
    Оценка:
    Сейчас где-то час потратил на то чтобы найти баг в следующем коде:

    #include <vector>
    
    struct Foo
    {
        Foo() {}
    
        void load(/*...*/)
        {
            v.clear(); // тут возникает assert "итераторы несовместимы"
        }
    
        std::vector<int> v;
    };
    
    struct Bar
    {
        Bar(Foo& f)
        {
            //...
            f.load(/*...*/);
        }
    };
    
    struct Holder
    {
        Holder()
            : bar(foo)
            , foo()
        {}
    
        Bar bar;
        Foo foo;
    };
    
    int main()
    {
        Holder h;
    }


    Как такого избежать?
    In Zen We Trust
    Re: [MSVC] Инициализация членов класса
    От: Abyx Россия  
    Дата: 18.04.11 16:12
    Оценка:
    Здравствуйте, Abyx, Вы писали:

    A>Как такого избежать?


    /Wall /analyse не помогает
    In Zen We Trust
    Re: [MSVC] Инициализация членов класса
    От: IROV..  
    Дата: 18.04.11 16:13
    Оценка:
    Здравствуйте, Abyx, Вы писали:

    A>Как такого избежать?


    MSVC 8 SP1 варнинги не пишет, и не ругаеться.

    Если у тебя пишет варнинги, то совет /WX
    я не волшебник, я только учусь!
    Re: [MSVC] Инициализация членов класса
    От: wander  
    Дата: 18.04.11 16:15
    Оценка:
    Здравствуйте, Abyx, Вы писали:

    A>Сейчас где-то час потратил на то чтобы найти баг в следующем коде:


    struct Holder
    {
        Holder()
            : foo() 
              bar(foo)
        {}
    
        Foo foo;
        Bar bar;
    };


    A>Как такого избежать?


    Местами поменяй инициализацию. Работаешь же с неинициализированной памятью.
    Re[2]: [MSVC] Инициализация членов класса
    От: IROV..  
    Дата: 18.04.11 16:22
    Оценка:
    Здравствуйте, wander, Вы писали:

    W>Местами поменяй инициализацию. Работаешь же с неинициализированной памятью.

    Чтото мне подсказывает что такая работа запрещена стандартом, хотя могу ошибаться
    я не волшебник, я только учусь!
    Re[3]: [MSVC] Инициализация членов класса
    От: wander  
    Дата: 18.04.11 16:30
    Оценка:
    Здравствуйте, IROV.., Вы писали:

    IRO>Чтото мне подсказывает что такая работа запрещена стандартом, хотя могу ошибаться

    Да что вы говорите :)
    Re[2]: [MSVC] Инициализация членов класса
    От: Abyx Россия  
    Дата: 18.04.11 16:57
    Оценка:
    Здравствуйте, wander, Вы писали:

    W>Местами поменяй инициализацию. Работаешь же с неинициализированной памятью.


    Это понятно. Мне интересно какие меры надо принять чтобы не повторить такую ошибку в будущем.
    In Zen We Trust
    Re[2]: [MSVC] Инициализация членов класса
    От: Abyx Россия  
    Дата: 18.04.11 17:01
    Оценка:
    Здравствуйте, IROV.., Вы писали:

    IRO>Писать


    IRO>: bar(this->foo)


    IRO>Тогда получишь варнинг


    очевидно это не тот варнинг

    еще можно написать "bar(!@#$%^)" и получить error
    In Zen We Trust
    Re[3]: [MSVC] Инициализация членов класса
    От: wander  
    Дата: 18.04.11 17:05
    Оценка:
    Здравствуйте, Abyx, Вы писали:

    A>Это понятно. Мне интересно какие меры надо принять чтобы не повторить такую ошибку в будущем.


    Ну что тут сказать. GCC это тоже не диагностирует. Поэтому остается только работать над собой, вырабатывать дисциплину и всегда проверять что за чем должно инициализироваться. А еще лучше отказаться по возможности от написания подобного кода. Ибо error prone.
    Re: [MSVC] Инициализация членов класса
    От: qqqqq  
    Дата: 18.04.11 17:10
    Оценка:
    gcc выдаст warning в этом случае. Кроме того, статические анализаторы кода должны такие и другие подобные ошибки ловить.
    Re[4]: [MSVC] Инициализация членов класса
    От: IROV..  
    Дата: 18.04.11 17:14
    Оценка:
    Здравствуйте, wander, Вы писали:

    W>Здравствуйте, IROV.., Вы писали:


    IRO>>Чтото мне подсказывает что такая работа запрещена стандартом, хотя могу ошибаться

    W>Да что вы говорите :)

    3.8/5

    Before the lifetime of an object has started but after the storage which the object will occupy has been allocated34)
    or, after the lifetime of an object has ended and before the storage which the object occupied is
    reused or released, any pointer that refers to the storage location where the object will be or was located
    may be used but only in limited ways. Such a pointer refers to allocated storage (3.7.3.2), and using the
    pointer as if the pointer were of type void*, is welldefined.
    Such a pointer may be dereferenced but the
    resulting lvalue may only be used in limited ways, as described below. If the object will be or was of a
    class type with a nontrivial
    destructor, and the pointer is used as the operand of a deleteexpression,
    the
    program has undefined behavior. If the object will be or was of a nonPOD
    class type, the program has
    undefined behavior if:
    — the pointer is used to access a nonstatic data member or call a nonstatic member function of the object, or
    — the pointer is implicitly converted (4.10) to a pointer to a base class type, or
    — the pointer is used as the operand of a static_cast (5.2.9) (except when the conversion is to
    void*, or to void* and subsequently to char*, or unsigned char*).
    — the pointer is used as the operand of a dynamic_cast (5.2.7).

    я не волшебник, я только учусь!
    Re[2]: [MSVC] Инициализация членов класса
    От: wander  
    Дата: 18.04.11 17:15
    Оценка:
    Здравствуйте, qqqqq, Вы писали:

    Q>gcc выдаст warning в этом случае.

    У меня 4.5 не выдает.

    -Wextra -Wall -ansi -pedantic -Weffc++

    Comeau тоже не выдает.
    Кроме того, мне кажется правильно, что не выдает. С какой стати-то

    Q>Кроме того, статические анализаторы кода должны такие и другие подобные ошибки ловить.

    Это да.
    Re[5]: [MSVC] Инициализация членов класса
    От: wander  
    Дата: 18.04.11 17:17
    Оценка:
    Здравствуйте, IROV.., Вы писали:

    IRO>3.8/5


    Позвольте, UB — это не запрещение. Это всего лишь предупреждение о том, что за последствия никто не ручается. Вот если бы такое не компилировалось, тогда да — запрещение.
    Re[2]: [MSVC] Инициализация членов класса
    От: Abyx Россия  
    Дата: 18.04.11 17:19
    Оценка:
    Здравствуйте, qqqqq, Вы писали:

    Q>gcc выдаст warning в этом случае. Кроме того, статические анализаторы кода должны такие и другие подобные ошибки ловить.


    да что вы говорите (с) не я
    In Zen We Trust
    Re[3]: [MSVC] Инициализация членов класса
    От: qqqqq  
    Дата: 18.04.11 17:21
    Оценка:
    W>У меня 4.5 не выдает.
    Ну не знаю, у меня все время выдавало, когда я с ним работал. Компилятор правда не для Intel, может в этом дело.
    Re: [MSVC] Инициализация членов класса
    От: Velheart Беларусь  
    Дата: 18.04.11 17:21
    Оценка:
    Здравствуйте, Abyx, Вы писали:

    A>Как такого избежать?


    Я всегда сразу же после добавления нового члена в класс, добавляю его в список инициализации в конструкторе, новые члены добавляю или в конец, или в конец логической группы членов, чтобы точно случайно не промахнуться и в списке инициализации все члены шли в порядке объявления, оно конечно примитивно и не ахти как идейно, но наряду с обязательной инициализацией локальных переменных, ассертами, подробными трэйсами и прочими штуками, без которых можно как бы и обойтись, в итоге сохраняет кучу времени =)
    Re[6]: [MSVC] Инициализация членов класса
    От: IROV..  
    Дата: 18.04.11 17:24
    Оценка:
    Здравствуйте, wander, Вы писали:

    W>Позвольте, UB — это не запрещение. Это всего лишь предупреждение о том, что за последствия никто не ручается. Вот если бы такое не компилировалось, тогда да — запрещение.


    буквоед?

    Для меня UB это запрет, просто трудно уловимый компилятором(поэтому он и не ругаеться).
    я не волшебник, я только учусь!
    Re[7]: [MSVC] Инициализация членов класса
    От: wander  
    Дата: 18.04.11 17:36
    Оценка:
    Здравствуйте, IROV.., Вы писали:

    IRO>буквоед?

    Не виноват я, оно само так

    IRO>Для меня UB это запрет, просто трудно уловимый компилятором(поэтому он и не ругаеться).

    Если на то пошло, то UB там из-за использования ссылки на невалидную память, а не из-за порядка инициализации. Порядок иницализации тут просто поспособствовал этому хорошо.
    Re[3]: [MSVC] Инициализация членов класса
    От: IROV..  
    Дата: 18.04.11 17:47
    Оценка:
    Здравствуйте, Abyx, Вы писали:

    A>Здравствуйте, IROV.., Вы писали:


    IRO>>Писать


    IRO>>: bar(this->foo)


    IRO>>Тогда получишь варнинг


    A>очевидно это не тот варнинг

    Тот-тот, он как раз и предупреждает программиста о том что — по мнению компилятора, мы здесь используем непроинициализированый указатель(this), и добром это не кончеться.

    A>еще можно написать "bar(!@#$%^)" и получить error

    как щас модно говорить в геймерских кругах, "удали студию"

    2.
    У меня в кодестайле прописано, что в конструкторах нельзя выполнять функции.
    Если нужно пишем — initialize, если до, значит нужен какойто менеджер.
    я не волшебник, я только учусь!
    Re[9]: [MSVC] Инициализация членов класса
    От: Хвост  
    Дата: 18.04.11 18:49
    Оценка:
    Здравствуйте, IROV.., Вы писали:

    IRO>Ну я именно это и хотел сказать, что дело не в порядке, а вообще в том что мы используем(разыменовываем) неготовый указатель.

    никакого разыменования (использования) там нет, вариант с this-> ты придумал сам.
    People write code, programming languages don't.
    Re[10]: [MSVC] Инициализация членов класса
    От: IROV..  
    Дата: 18.04.11 19:19
    Оценка:
    Здравствуйте, Хвост, Вы писали:

    Х>Здравствуйте, IROV.., Вы писали:


    IRO>>Ну я именно это и хотел сказать, что дело не в порядке, а вообще в том что мы используем(разыменовываем) неготовый указатель.

    Х>никакого разыменования (использования) там нет, вариант с this-> ты придумал сам.

    9.3.2
    я не волшебник, я только учусь!
    Re[10]: [MSVC] Инициализация членов класса
    От: wander  
    Дата: 18.04.11 19:36
    Оценка:
    Здравствуйте, Хвост, Вы писали:

    Х>Здравствуйте, IROV.., Вы писали:


    IRO>>Ну я именно это и хотел сказать, что дело не в порядке, а вообще в том что мы используем(разыменовываем) неготовый указатель.

    Х>никакого разыменования (использования) там нет, вариант с this-> ты придумал сам.
    Как это нет??!
    struct Bar
    {
        Bar(Foo & f)
        {
            //...
            f.load(); //а это что?
        }
    };
    Re: [MSVC] Инициализация членов класса
    От: martin Беларусь  
    Дата: 18.04.11 19:38
    Оценка:
    Здравствуйте, Abyx, Вы писали:

    A>Сейчас где-то час потратил на то чтобы найти баг в следующем коде:


    A>
    A>#include <vector>
    
    A>struct Foo
    A>{
    A>    Foo() {}
    
    A>    void load(/*...*/)
    A>    {
    A>        v.clear(); // тут возникает assert "итераторы несовместимы"
    A>    }
    
    A>    std::vector<int> v;
    A>};
    
    A>struct Bar
    A>{
    A>    Bar(Foo& f)
    A>    {
    A>        //...
    A>        f.load(/*...*/);
    A>    }
    A>};
    
    A>struct Holder
    A>{
    A>    Holder()
    A>        : bar(foo)
    A>        , foo()
    A>    {}
    
    A>    Bar bar;
    A>    Foo foo;
    A>};
    
    A>int main()
    A>{
    A>    Holder h;
    A>}
    A>


    A>Как такого избежать?


    Посмотри в сторону boost::base_from_member.
    Re[11]: [MSVC] Инициализация членов класса
    От: Хвост  
    Дата: 18.04.11 19:42
    Оценка:
    Здравствуйте, wander, Вы писали:

    W>Как это нет??!


    я вообще не об этом говорю, я говорю о том что использование проинициализированных полей объекта до полной инициализации самого объекта не является UB, как в этом пытается убедить нас IROV.
    People write code, programming languages don't.
    Re[11]: [MSVC] Инициализация членов класса
    От: IROV..  
    Дата: 18.04.11 19:44
    Оценка:
    Здравствуйте, wander, Вы писали:

    W>
    W>struct Bar
    W>{
    W>    Bar(Foo & f)
    W>    {
    W>        //...
    W>        f.load(); //а это что?
    W>    }
    W>};
    W>


        Holder()
            : bar(foo) //а это что???


    я не волшебник, я только учусь!
    Re[11]: [MSVC] Инициализация членов класса
    От: IROV..  
    Дата: 18.04.11 19:45
    Оценка:
    Здравствуйте, wander, Вы писали:

    W>Как это нет??!

    W>
    W>struct Bar
    W>{
    W>    Bar(Foo & f)
    W>    {
    W>        //...
    W>        f.load(); //а это что?
    W>    }
    W>};
    W>

    Кстати тут разыменования нету

    void load(/*...*/)
        {
            v.clear(); // оно в дебрях там
        }


    я не волшебник, я только учусь!
    Re[12]: [MSVC] Инициализация членов класса
    От: wander  
    Дата: 18.04.11 19:46
    Оценка:
    Здравствуйте, Хвост, Вы писали:

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


    W>>Как это нет??!


    Х>я вообще не об этом говорю, я говорю о том что использование проинициализированных полей объекта до полной инициализации самого объекта не является UB, как в этом пытается убедить нас IROV.

    Так тут как раз используется непроинициализированное. Что касается выделенного, мне не кажется, что он в этом пытается нас убедить.
    Re[12]: [MSVC] Инициализация членов класса
    От: wander  
    Дата: 18.04.11 19:50
    Оценка:
    Здравствуйте, IROV.., Вы писали:

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


    IRO>Кстати тут разыменования нету


    Зато ссылка есть. Я выделил использование.

    IRO>

    Re[2]: [MSVC] Инициализация членов класса
    От: Abyx Россия  
    Дата: 18.04.11 20:08
    Оценка:
    Здравствуйте, martin, Вы писали:

    M>Посмотри в сторону boost::base_from_member.


    посмотрел и не понял что вы хотите предложить.
    In Zen We Trust
    Re[3]: [MSVC] Инициализация членов класса
    От: martin Беларусь  
    Дата: 18.04.11 20:50
    Оценка:
    Здравствуйте, Abyx, Вы писали:

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


    M>>Посмотри в сторону boost::base_from_member.


    A>посмотрел и не понял что вы хотите предложить.


    Насколько я понимаю, в вашем примере проблема в том что bar пытается использовать объект foo который еще не создан. Проблему конечно можно избежать поменяв местами объявления членов bar и foo класса Holder. Тогда все будет ок. Но в будущем нельзя гарантировать что кто-нибудь их опять не поменяет случайно местами. Самое правильное, на мой взгляд, это сделать гарантированный вызов конструктора foo перед вызовом конструктора bar. Этого можно добиться с использованием наследования.

    struct HolderBase 
    {
       Foo foo;
    };
    
    struct Holder : protected HolderBase
    {
        Holder()
            : bar(foo)
        {}
    
        Bar bar;
    };


    Это конечно не совсем Base-from-Member, но близко к нему.
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.