[Bug][VC] Cнова?
От: _nn_  
Дата: 30.05.10 11:48
Оценка: 35 (2) -1 :))) :))) :))) :)
Простой код

struct base
{
  int i;
  char c;
};

struct derived : base
{
  double d;
};

#include <stdio.h>

int main()
{  
 base b = base();
 printf("b.i - %d\n", b.i);
 printf("b.c - %d\n", (int)b.c);

 derived d = derived();
 printf("d.i - %d\n", d.i);
 printf("d.c - %d\n", (int)d.c);
 printf("d.d - %f\n", d.d);
}


G++ 4.4.3

b.i — 0
b.c — 0
d.i — 0
d.c — 0
d.d — 0.00000


VC 2008, 2010

b.i — 0
b.c — 0
d.i — -858993460
d.c — -52
d.d — -925596....


Если не наследоваться, то работает нормально:
struct derived /* : base*/
{
  base b;
  double d;
};


А также работает через new
derived* pd = new derived();
derived& d = *pd;

...


К счастью нашлось более элегантное решение через placement new:
derived d;
new (&d) derived();


Тут можно возразить, и посоветовать memset.
Однако memset не будет хорошо работать для классов с нетривиальными конструкторами.

Если добавить класс с нетривиальным конструктором, VC конкретно лажает:
struct nontrivial
{
  nontrivial() : member(4) {}
  ~nontrivial() {}

  int member;
};

struct base
{
  int i;
  char c;

  nontrivial n;
};

struct derived : base
{
  double d;
};

#include <stdio.h>
#include <new>

int main()
{  
 base b = base();
 printf("b.i - %d\n", b.i);
 printf("b.c - %d\n", (int)b.c);
 printf("b.n.member - %d\n", b.n.member);

 derived d = derived();
 new (&d) derived(); // Workaround ??
 printf("d.i - %d\n", d.i);
 printf("d.c - %d\n", (int)d.c);
 printf("d.d - %f\n", d.d);
}


Вывод

b.i — -858993460
b.c — -52
b.n.member — 4
d.i — -858993460
d.c — -52
d.d — -925596....


Тут уже ничего не помогает. Даже new base() не работает.

В общем какой-то баг с инициализацией.
Берегитесь
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: [Bug][VC] Cнова?
От: Caracrist https://1pwd.org/
Дата: 30.05.10 12:02
Оценка:
Здравствуйте, _nn_, Вы писали:


__>VC 2008, 2010

VC 2005 same shit (debug)
__>

__>b.i — 0
__>b.c — 0
__>d.i — -858993460
__>d.c — -52
__>d.d — -925596....


2005 release:

b.i — 0
b.c — 0
d.i — 4206624
d.c — 40
d.d — 0.000000


__>Берегитесь
~~~~~
~lol~~
~~~ Single Password Solution
Re: [Bug][VC] Cнова?
От: Caracrist https://1pwd.org/
Дата: 30.05.10 12:18
Оценка:
Здравствуйте, _nn_, Вы писали:


__>Если добавить класс с нетривиальным конструктором, VC конкретно лажает:



и не только VC:
http://codepad.org/3iS30XBJ (g++ 4.1.2)

b.i — 0
b.c — 36
b.n.member — 4
d.i — 1076296996
d.c — 36
d.d — 0.000000
d.n.member — 4




__>В общем какой-то баг с инициализацией.

__>Берегитесь
~~~~~
~lol~~
~~~ Single Password Solution
Re: [Bug][VC] Cнова?
От: Alximik509 Россия  
Дата: 30.05.10 12:43
Оценка: +1
Чета я нифига не понял.. В чем баг то?
или это типо шутка?
Re: [Bug][VC] Cнова?
От: rm822 Россия  
Дата: 30.05.10 12:44
Оценка:
Нету никакого бага, ты не инициализировал переменные и бай дефолт vc заполняет их 0хСС
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: [Bug][VC] Cнова?
От: Ops Россия  
Дата: 30.05.10 13:11
Оценка:
Здравствуйте, _nn_, Вы писали:

<...>

__>В общем какой-то баг с инициализацией.


Можно ссылочку на стандарт, где написано, что там должны быть нули? Я просто давно в это не вникал, т.к. не использую переменные до их явной инициализации.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[2]: [Bug][VC] Cнова?
От: ilvi Россия  
Дата: 30.05.10 13:35
Оценка:
Здравствуйте, rm822, Вы писали:

R>Нету никакого бага, ты не инициализировал переменные и бай дефолт vc заполняет их 0хСС


А чем тогда является: derived d = derived(); ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[2]: [Bug][VC] Cнова?
От: _nn_  
Дата: 30.05.10 13:44
Оценка:
Здравствуйте, rm822, Вы писали:

R>Нету никакого бага, ты не инициализировал переменные и бай дефолт vc заполняет их 0хСС


Тогда почему тут печатает разные числа ?

#include <stdio.h>

#include <string>

struct check
{
    std::string s;
    int i;
};

static check c = check();
static check d;

struct basecheck2
{
    int i;
};

struct check2 : basecheck2
{
    char c;
};

static check2 c2 = check2();
static check2 d2;

int main()
{
  printf("%d\n", c.i);
  printf("%d\n", c2.i);
}


0
-858993460

http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: [Bug][VC] Cнова?
От: quodum  
Дата: 30.05.10 14:06
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Тогда почему тут печатает разные числа ?


Потому что check -- не POD.
Re: [Bug][VC] Cнова?
От: quodum  
Дата: 30.05.10 14:14
Оценка:
Здравствуйте, _nn_,

8.5:9

If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a non-static object, the object and its subobjects, if any, have an indeterminate initial value; if the object or any of its subobjects are of const-qualified type, the program is ill-formed.

Re: [Bug][VC] Cнова?
От: Masterkent  
Дата: 30.05.10 14:15
Оценка:
Это, в общем-то, известный баг VC++ — он, похоже, не учитывает правила value-инициализации C++03, а следует устаревшему стандарту 98-го года.
Re[2]: [Bug][VC] Cнова?
От: Masterkent  
Дата: 30.05.10 14:29
Оценка:
quodum:

Q>8.5:9

Q>

If no initializer is specified for an object [...]

Это тут вообще не при чём. См. C++03 — 5.2.3/2 и 8.5/5.
Re[4]: [Bug][VC] Cнова?
От: ilvi Россия  
Дата: 30.05.10 14:37
Оценка:
Здравствуйте, quodum, Вы писали:

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


__>>Тогда почему тут печатает разные числа ?


Q>Потому что check -- не POD.


Давайте усложним и добавим к примеру создание объекта:

struct basecheck2
{
    int i;
};
static basecheck2 b = basecheck2();
...
//и вывод его на печать

  printf("%d\n", c.i);
  printf("%d\n", c2.i);
  printf("%d\n", b.i);


0
-858993460
0


Это вс2010. basecheck2 — POD и что теперь?
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[3]: [Bug][VC] Cнова?
От: ilvi Россия  
Дата: 30.05.10 14:41
Оценка:
Здравствуйте, _nn_, Вы писали:

codepad по другому глючит. добавил вывод для объекта типа basecheck2.
http://codepad.org/waCq7obR

#include <stdio.h>

#include <string>

struct check
{
    std::string s;
    int i;
};

static check c = check();
static check d;

struct basecheck2
{
    int i;
};

struct check2 : basecheck2
{
    char c;
};

static check2 c2 = check2();
static check2 d2;

static basecheck2 b = basecheck2();

int main()
{
  printf("%d\n", c.i);
  printf("%d\n", c2.i);
  printf("%d\n", b.i);
}



Output:
134543672
0

0

... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[3]: [Bug][VC] Cнова?
От: quodum  
Дата: 30.05.10 23:10
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>quodum:


Q>>8.5:9

Q>>

If no initializer is specified for an object [...]

M>Это тут вообще не при чём. См. C++03 — 5.2.3/2 и 8.5/5.

А, точно.
Re: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 31.05.10 09:14
Оценка: -1
Здравствуйте, _nn_, Вы писали:

<>

Для POD-типов запись T x = T(), *px = new T() — это value-initialization, приводящая к zero-initialization.
Тогда как для не-POD-типов — это default-initialization.
Поскольку derived формально является не-POD, то у него есть неявный конструктор без параметров, не инициализирующий POD-базы и члены.
Отсюда и мусор.

Статические же объекты всегда сначала обнуляются, а потом уже инициализируются в рантайме. (Компилятор вправе оптимизировать это, сразу инициализировав статическое хранилище константами).
Кстати, эта двухступенчатая инициализация является источником unspecified behavior (а то и undefined, если постараться ) при обращении к статическим объектам.

С вашего позволения, не приведу цитаты стандарта, а только укажу параграфы
— 3.6.2 Start and termination / Initialization of non-local objects
— 8.5:5 Initializers / zero-, default-, value-initializer
— 12.6.2:4 Special member functions / Initializing bases and members
Впрочем, последнее как раз и стоит процитировать.

If a given nonstatic data member or base class is not named by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer), then
If the entity is a nonstatic data member of (possibly cv-qualified) class type (or array thereof) or a base class, and the entity class is a non-POD class, the entity is default-initialized (8.5). If the entity is a nonstatic data member of a const-qualified type, the entity class shall have a user-declared default constructor.
Otherwise, the entity is not initialized. If the entity is of const-qualified type or reference type, or of a (possibly cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of a const-qualified type, the program is ill-formed.


Вот такая грабля.
Перекуём баги на фичи!
Re[2]: [Bug][VC] Cнова?
От: ilvi Россия  
Дата: 31.05.10 10:07
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Для POD-типов запись T x = T(), *px = new T() — это value-initialization, приводящая к zero-initialization.

К>Тогда как для не-POD-типов — это default-initialization.
К>Поскольку derived формально является не-POD, то у него есть неявный конструктор без параметров, не инициализирующий POD-базы и члены.
К>Отсюда и мусор.

Для не-POD без конструктора точно так будет в случае: T x = T(), *px = new T() ?
Не должна ли рекурсивно для всех членов вызваться value-initialization ?
Re[3]: [Bug][VC] Cнова?
От: kvser  
Дата: 31.05.10 10:15
Оценка:
Здравствуйте, ilvi, Вы писали:

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


К>>Для POD-типов запись T x = T(), *px = new T() — это value-initialization, приводящая к zero-initialization.

К>>Тогда как для не-POD-типов — это default-initialization.
К>>Поскольку derived формально является не-POD, то у него есть неявный конструктор без параметров, не инициализирующий POD-базы и члены.
К>>Отсюда и мусор.

I>Для не-POD без конструктора точно так будет в случае: T x = T(), *px = new T() ?

I>Не должна ли рекурсивно для всех членов вызваться value-initialization ?

http://rsdn.ru/Forum/Info/FAQ.cpp.newnnew.aspx
Автор: Андрей Тарасевич
Дата: 07.12.04
Re[3]: [Bug][VC] Cнова?
От: Кодт Россия  
Дата: 31.05.10 10:20
Оценка: -1
Здравствуйте, ilvi, Вы писали:

К>>Для POD-типов запись T x = T(), *px = new T() — это value-initialization, приводящая к zero-initialization.

К>>Тогда как для не-POD-типов — это default-initialization.
К>>Поскольку derived формально является не-POD, то у него есть неявный конструктор без параметров, не инициализирующий POD-базы и члены.
К>>Отсюда и мусор.

I>Для не-POD без конструктора точно так будет в случае: T x = T(), *px = new T() ?

I>Не должна ли рекурсивно для всех членов вызваться value-initialization ?

Сказано же: рекурсивно вызывается либо default-initialization (если элемент — не-POD), либо ничего не вызывается.
Итого, если развернуть всё дерево, ни один член не будет инициализирован, если это не делается явно.

Да, это подлянка, зашитая в стандарт, ради того, чтобы не платить за то, что не прошено.
Вот если бы в языке было две формы конструктора "без параметров" — минимальный и тотальный...
Перекуём баги на фичи!
Re[4]: [Bug][VC] Cнова?
От: ilvi Россия  
Дата: 31.05.10 10:26
Оценка:
Здравствуйте, kvser, Вы писали:

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


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


К>>>Для POD-типов запись T x = T(), *px = new T() — это value-initialization, приводящая к zero-initialization.

К>>>Тогда как для не-POD-типов — это default-initialization.
К>>>Поскольку derived формально является не-POD, то у него есть неявный конструктор без параметров, не инициализирующий POD-базы и члены.
К>>>Отсюда и мусор.

I>>Для не-POD без конструктора точно так будет в случае: T x = T(), *px = new T() ?

I>>Не должна ли рекурсивно для всех членов вызваться value-initialization ?

K>http://rsdn.ru/Forum/Info/FAQ.cpp.newnnew.aspx
Автор: Андрей Тарасевич
Дата: 07.12.04



Если это не-POD-класс-тип без явно объявленного конструктора, то в первом случае будет рекурсивно применена value-initialization к каждому подобъекту этого класса (что при этом получится — зависит о типов этих подобъектов),


Первый случай там

new T();


Или я под вечер чего-то не понимаю уже?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.