C++/STL и memset

Andbar

Преамбула.
Искал причину довольно странного мемлика. Память выделялась где-то в глубине stl-я при вызове wstring::operator+=, но затем указатель затирался. Отправил данную информацию к владельцу текущего модуля, тот за выходные локализировал причину: структура, в которую входило несколько строк, инициализировалась строчкой вида "memset(&m_mystruc, 0, sizeof(m_mystruc;" в конструкторе класса-владельца структуры. Вот и получалось, что внутренние данные сконструированных строк разрушались. После этого запустил поиск по всем исходникам проекта слова memset и просматриваю каждое вхождение (в особенности вхождения типа "class SomeClass{SomeClass{memset(this, 0, sizeof(*this};...};", которых нашлось не мало). Самое интересное, что подобная гадость находится.
А вот теперь собственно вопрос.
Является ли частое использование memset (в особенности для инициализации данных объекта/структуры) признаком плохого стиля или же невозможность использовать memset на STL-ных строках являются недостатком реализации библиотеки (используемой в студии)?
С одной стороны, очень удобно писать так:
typedef struct tagmyStruct{
tagmyStruct{memset(this, 0, sizeof(tagmyStruct};
int a;
int b;
size_t c;
unsigned char *c;
} myStruct, *pmyStruct;
Так как при добавлении полей не нужно будет думать о их инициализации. Но с другой стороны, если мы добавляем туда wstring someStr; или другое подобное поле со своим конструктором, мы рискуем нарваться на мемлики или другие ошибки... С другой стороны, зануление области памяти по частям удлиняет код, так что имеет смысл хотя-бы часть полей занулить через memset (во всяком случае, если структура или класс часто создаётся).
Кто что думает по этому поводу?
зы: заранее прошу прощения если тема уже поднималась: пишу на C++ только с прошлого года, а до того соответствующие темы почти не читал.

kokoc88

Кто что думает по этому поводу?
Думаем, что пока такие темы будут здесь появляться, недальновидные личности будут продолжать писать, что C++ - полное гавно. :cool:

procenkotanya

memset в конструкторе использовать можно
Я правильно понял, что в твоём примере источник проблем — вызов memset на уже сконструированную структуру из объекта другого класса? Если да, то нафига так делать, ясно же что для членов деструкторы не будут вызваны?

kruzer25

C++ - полное говно, зачем ты на нём пишешь?

Andbar

Если да, то нафига так делать, ясно же что для членов деструкторы не будут вызваны?
это почему? Студия вызывает.
Короче, пример.
Вася Пупкин написал класс:
class VPupkin_Class
{
int m_int;
char *m_char;
size_t m_charlen;
char m_arr[32];
public:
VPupkin_Class
{
memset(this, 0, sizeof(*this;
m_int = 3;
}
//здесь куча других функций
};

Потом он уволился, а вместо него над кодом начал работать Петя Индишный. В ходе написания новой версии, им потребовалось добавить пару полей в класс VPupkin_Class. Ему было лень писать свой класс-наследник и он просто модифицировал класс Васи:
class VPupkin_Class
{
int m_int;
char *m_char;
size_t m_charlen;
char m_arr[32];
string m_name;
wstring m_somewstring;
public:
VPupkin_Class
{
memset(this, 0, sizeof(*this;
m_int = 3;
}
//здесь куча других функций
void SetName(char* name)
{
m_name = name;
}
//.....
};

И получаем мемлики, т.к. в момент выполнения конструктора VPupkin_Class, конструкторы для m_name и m_somewstring уже вызваны.
зы: в моём случае было конечно хуже:
typedef struct {int field;wstring somestr;....} AStruct;
class SomeClass
{
...
AStruct m_struct;
...
public:
SomeClass
{
.....
memset(m_struct, 0, sizeof(AStruct;
....
}
};
Но подозреваю, что когда-то в AStruct строк небыло.

kruzer25

class VPupkin_Class
{
int m_int;
char *m_char;
size_t m_charlen;
char m_arr[32];
public:
VPupkin_Class
{
memset(this, 0, sizeof(*this;
m_int = 3;
}
//здесь куча других функций
};

class VPupkin_Class
{
int m_int;
char *m_char;
size_t m_charlen;
char m_arr[32];
string m_name;
wstring m_somewstring;
public:
VPupkin_Class
{
memset(this, 0, sizeof(*this;
m_int = 3;
}
//здесь куча других функций
void SetName(char* name)
{
m_name = name;
}
//.....
};

typedef struct {int field;wstring somestr;....} AStruct;
class SomeClass
{
...
AStruct m_struct;
...
public:
SomeClass
{
.....
memset(m_struct, 0, sizeof(AStruct;
....
}
};

Спасибо, подрочил. Говнокодьте ещё.

Andbar

Вот, кстати, интересная ссылка на счёт инициализации.
http://alenacpp.blogspot.com/2006/11/blog-post.html

slonishka

я вот к C привык и сегодня тоже долго не мог понять, почему:
struct my_str {
int a;
std::string str;
};

my_str *my = (my_str *) malloc(sizeof(my_str;

создает указатель на какую-то неадекватную хрень. :grin:

sbs-66

memset для инициализации можно использовать только для обнуления структур, которые нужны для вызова некоторых WinAPI методов и описаны в Platform SDK. Больше для инициализации memset юзать нигде нельзя, да и не для инициализации тоже нежелательно.

lada05

Радист, бесишь :mad:
Плохому танцоруююю
struct tagmyStruct{
  tagmyStruct : a(0b(0c(0d(0str("string") {};
  int a;
  int b;
  size_t c;
  unsigned char *d;
  std::string str;
};
кстати очень странно, что ты лик получил, а не сегфолт, обнуляя все что не попадя мемсетом
вот тебе еще один пример, хоть и не по теме
class Base {
public:
virtual void p {
}
};
class Derived : public Base {
public:
void p {
}
};
int main
{
    Derived * p = new Derived;
    memset(p,0,sizeof(Derived;
    p->p;
}

karkar

По-хорошему нужно убрать memset и инициализировать все в конструкторе.
Если очень хочется memset, то можно применить его для структур с элементарными полями, а более сложные поля (типа stl-ных и других с конструкторами) добавлять в производный класс. Их конструкторы тогда будут вызваны после мемсета простых полей (который останется в базовом). Но это требует дисциплины, как впрочем и первый вариант..

kokoc88

memset для инициализации можно использовать только для обнуления структур, которые нужны для вызова некоторых WinAPI методов
Так то ведь C, а не C++. :cool:

vasena

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

evolet

попробую ответить по-нормальному...
имхо , использовать memset для инициализации POD-типа (Plain Old Data - ботай , что это такое вполне нормално,
в конструкторе этого пода или извне
Если добавляется член - не встроенный тип (например std::string то тип перестает быть подом и инициализация memset'ом становится undefined behavior (при дальнейшем использовании этого объекта, в т.ч. удалении).
Если некий чувак добавляет новый член к типу и не удосуживается посмотреть-поправить конструкторы этого типа - этому чуваку можно только посоветовать никогда не программировать на С++.
Вообще с этим подами может случится засада, если какой-то внешний код (которой априори не просмотришь) закладывается на то, что это именно под (использует memset'ы , memcpy и прочие чисто С-приемы). В этом случае нельзя превращать под в не-под. имхо в комментах к типу должно быть написано, существенно ли то, что он под.
PS только вот я что-то я забыл, добавление конструктора к поду далает ли его не-подом? Если делает, то memset'ом пользоваться нельзя.
PPS имхо, что-то ты не то читаешь, эту Алену С++ читал по-диагонали, но она имхо не рюхает. Для начала могу посоветовать Мейерса Эффективное использование С++ (третье издание, обязательно третье там и про порядок конструирования со всеми заморочками по-моему тоже есть и с "философскими обоснованиями"

Andbar

memset для инициализации можно использовать только для обнуления структур, которые нужны для вызова некоторых WinAPI методов и описаны в Platform SDK. Больше для инициализации memset юзать нигде нельзя, да и не для инициализации тоже нежелательно.
Ясно. Ну примерно так я и представлял, просто перед глазами был проект, в котором memset иногда используется для инициализации структур и классов без виртуальных функций... Только вот структуры иногда сами содержали в себе объекты других классов.

Andbar

PPS имхо, что-то ты не то читаешь, эту Алену С++ читал по-диагонали, но она имхо не рюхает. Для начала могу посоветовать Мейерса Эффективное использование С++ (третье издание, обязательно третье там и про порядок конструирования со всеми заморочками по-моему тоже есть и с "философскими обоснованиями"
я не писал, что ботаю C++ по её постам, просто некоторые вещи подсматриваю у неё.
В общем, спасибо за детальное описание.

kokoc88

Если некий чувак добавляет новый член к типу и не удосуживается посмотреть-поправить конструкторы этого типа - этому чуваку можно только посоветовать никогда не программировать на С++.
Этому чуваку лучше только посочувствовать и порекомендовать уволиться с поддержки такого гавна и пойти на нормальный проект. Тем более он добавляет тип, у которого есть конструктор по умолчанию, в нашей истории это std::string. Несмотря на то, что memset может работать правильно, так не пишут на C++. Ровно как и ручной захват и освобождение ресурсов: кто-то может добавить return или throw. Нельзя же сказать, что этот кто-то не умеет программировать только потому, что он заметил, что в каких-то глубинах какой-то мудак залочил мьютекс руками.

evolet

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

evolet

да ,но если этот первый - начинающий прогер, то имхо нужно применять не драконовские меры, а скорее исправительно-воспитательные, в надежде, что он проникнется тем, какую х-ню сделал и больше так делать не будет...

Dasar

Если некий чувак добавляет новый член к типу и не удосуживается посмотреть-поправить конструкторы этого типа - этому чуваку можно только посоветовать никогда не программировать на С++.
вот этот шаг странный
не понятно зачем надо надо смотреть конструктор, если я добавляю в класс поле std::string.

evgen5555

не понятно зачем надо надо смотреть конструктор, если я добавляю в класс поле std::string.
Да действительно, тебе смотреть не надо. Умные люди потом разберутся :grin:

Andbar

не понятно зачем надо надо смотреть конструктор, если я добавляю в класс поле std::string.
Ну если работать на проекте, над которым не работали ни индусы, ни люди, которые иногда применяют сишные приёмы в C++, то может и не нужно во всём разбираться, а в более общем случае лучше разбираться как что работает... Я бы при любом изменении поинтересовался всеми участками кода, которые могут как-либо взаимодействовать с изменением.

evolet

вот этот шаг странный
не понятно зачем надо надо смотреть конструктор, если я добавляю в класс поле std::string.
ну одно из формальных объяснений - это пример как раз из этого треда
...
я сейчас подумал, если все написано в "правильном" ООП стиле, то наверное ничего от просто добавления члена сломаться не должно (опять-же, может еще есть заморочки, кроме подов, из-за которых все может сломаться, про тот же самый под, боюсь, не каждый вспомнит, когда будет правки вносить, а так - посмотрел - и сразу вспомнил , и потом через пол года не надо отлавливать утечки памяти)
а так, класс - это же не контейнер из членов, соответственно конструироваться на логическом уровне члены должны "все вместе". Даже в случае, если это инициализация простая, т.е. достаточно конструктора по умолчанию, взгянуть на конструктор и убедиться , что все ОК - не сложно. Я считаю, что это должно быть в привычке, типа той, что если ты в большой функции заводишь во вложенной области переменную, надо убедиться, что переменной с этим же именем нет во внешней области видимости (ну или типа знать точно, что на такое компилятор ругается, как в С#, если я правильно помню

kokoc88

взгянуть на конструктор и убедиться , что все ОК - не сложно
А если его не видно?

evolet


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

kokoc88

тогда ты не сможешь и член добавить, т.к. тогда и опредления класса не должно быть видно
Определение может быть видно. В производный класс я смогу добавить что-нибудь, что умрёт из-за неправильного подхода к программированию на C++. Да и не в этом дело, если работаешь с адекватными людьми, у такой ерунде даже не думаешь. Поэтому и сам должен заботиться о правильности своего кода.

evolet

не вполне тебя понял, но
1) видеть опредление класса (в доке или выкачать с правами только для чтения или...) - это одно, а возможность внести туда изменения - это другое
2) наследование это - одно , а добавление члена - это другое

evolet

В производный класс я смогу добавить что-нибудь, что умрёт из-за неправильного подхода к программированию на C++.
аааа, ну если , например, в конструктор производного добавить meset(this, 0, sizeof(... то да, конечно, че-нить интересное наверняка получится

Andbar

Кстати, я правильно понимаю, что такой кусок кода некорректен в общем случае? Или в стандарте явно прописано, в каком порядке должна следовать память объектов при наследовании?
//ZONE - некая POD-структура
class CZone : public ZONE
{
//определение дополнительных полей, методов (в т.ч. виртуальных конструктора и деструктора
};
.....
CZone zone;
memset(&zone, 0, sizeof(ZONE;

bleyman

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

sbs-66

Так делать не надо в любом случае. Однако при наследовании в памяти располагается сначала базовый класс, а потом поля наследника. Не знаю уж, по стандарту это или просто так принято, но есть куча кода, который на это расчитывает, в т.ч. и в WinAPI.
PS. И да, FJ прав, если потом CZone будет не первым базовым классом при множественном наследовании, то аналогичный код для экземпляров того класса, конечно же, сломается.

karkar

//определение дополнительных полей, методов (в т.ч. виртуальных конструктора и деструктора
.....
memset(&zone, 0, sizeof(ZONE;

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

Andbar

А мемсет разве не потрет указатель на таблицу виртуальных функций? Такой объект потом не стоит трогать даже палкой..
ну дальнейший код вроде работает, при чём это дело компилится как студией, так и gcc, так что наверное указатель стоит после первых полей.

slonishka

ну дальнейший код вроде работает, при чём это дело компилится как студией, так и gcc, так что наверное указатель стоит после первых полей.
тебе заняться чтоли нечем больше. нахуя писать хуево, когда можно написать нормально.
я чего-то не понимаю, наверное.
зы: на компе у заказчика undefined behaviour *всегда* рассылает спам, портит пароли и рушит корпоративный сервер.

Andbar

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

kokoc88

по стандарту это или просто так принято, но есть куча кода, который на это расчитывает, в т.ч. и в WinAPI.
Если только MFC, WINAPI - это C, там нету классов. :cool:

evolet

такой код некорректен почти наверное.
если в CZone есть виртуальные методы то там значит будет указатель на vtbl и memset(&zone, 0, sizeof(ZONE;-ом ты его просто затрешь (по-моему указатель на vtbl обычно в начале располагается)
расположение членов в памяти стандарт гарантирует только для подов (а все структуры в WinAPI являются подами - и это существенно)
в общем случае располежение в памяти объекта - не пода стандартом не регламентируется и остается на усмотрение компилятора. Да, обычно компиляторы располагают члены и базовые классы по порядку, но закладываться на это - это писать непортабельный код.
че-то я сейчас засомневался: если просто пронаследоваться - будет ли уже это под или нет? Признаться, я не читаю стандарт перед сном и не дрочу на изображения Страуструпа (с)
вообще у подов довольно ограниченная область применения, пихать их везде , где получается (например, из-за кажущихся удобств написания в конструкторе memset и все) - не гуд, это уже какое-то адово смешение С и С++ начинается
поды обычно используются, когда нужна бинарная совместимость между модулями, компилирующимися отдельно (пример - вызовы WinAPI)

slonishka

ну ладно, соболезную тогда.

sbs-66

Если только MFC, WINAPI - это C, там нету классов.
Да, это я потупил. Там есть структуры, которые расширяют другие структуры, при этом в памяти идёт сначала базовая структура, а потом поля расширенной. Но там таки не наследование, а тупо в расширенной структуре первый элемент - базовая структура. Хотя эффект такой же, но таки не наследование.

slonishka

есть, кстати, клевый макрос offsetof, может не знает кто. :D

karkar

ну дальнейший код вроде работает
Это временно.
Простой пример:
#include <windows.h>

class bomb
{
public:
int a,b;
virtual void hello
{
printf("hello\n");
}
};

int _tmain(int argc, _TCHAR* argv[])
{
bomb onstack;
memset(&onstack, 0, sizeof(bomb;
onstack.hello;

bomb *onheap = new bomb;
memset(onheap, 0, sizeof(bomb;
onheap->hello;
return 0;
}

Компилял в VS2005.
Когда объект создается на стеке, вызов проходит успешно, т.к. он просто инлайнится и к таблице вирт. функций не обращается.
А вот когда в куче, идет обращение через таблицу и все падает, что и требовалось ожидать.

Nqstya1710

upd: я что-то не совсем в тему влез, что тут о под разговор :)

Andbar

В данном конкретном случае, ZONE - это POD-структура.
Может memset(&zone, 0, sizeof(ZONE; заменить на memset(&zone + offsetof(CZone, имя_первого_поля_в_ZONE 0, sizeof(ZONE; ?

vasena

Общий рецепт придумать нельзя, так как все сильно завязано на компилятор (реализацию наследования размещение в памяти классов ). В данном примере, первое поле в памяти может быть совсем и не первым, например, для компактности расположения.

Nqstya1710

у меня такой вопрос, возможно, его уже кто-то задавал.
если у супертипа нет виртуальных функций и тп, зачем от него вообще наследовать или его исправлять?
может, лучше сделать аггрегацию?
class CZone
{
public:
ZONE zone;
*****************
};

Andbar

Общий рецепт придумать нельзя, так как все сильно завязано на компилятор (реализацию наследования размещение в памяти классов ). В данном примере, первое поле в памяти может быть совсем и не первым, например, для компактности расположения.
Я уже об этом думал. Можно взять любое поле и использовать код вида:
memset(&zone + offsetof(CZone, имя_поля_в_ZONE) - offsetof(ZONE, имя_поля_в_ZONE 0, sizeof(ZONE;

Nqstya1710

тут один друг в шутку сказал, что наследование лучше аггрегации тем, что точек меньше ставить нужно :)
почему бы, в случае наследования, не сделать приведение типов, а потом memset?
CZone c_zone;
ZONE* zone = &c_zone;
memset( zone, 0, sizeof( zone;

kokoc88

Можно взять любое поле и использовать код вида:
А ещё можно не страдать хернёй, убрать memset и написать нормальный C++ конструктор.

kokoc88

почему бы, в случае наследования, не сделать приведение типов, а потом memset?
Потому что от приведения типов адрес не меняется.

evolet

Потому что от приведения типов адрес не меняется.
быстро сотри свой пост, пока никто не видел)

margadon

:o а как же множественное наследование?..

Nqstya1710

Потому что от приведения типов адрес не меняется.
во-первых, только что проверил, что при множественном наследовании меняется адрес при приведении:
вот код (под gcc)

#include <stdio.h>
#include <string.h>

class ZONE
{
public:
ZONE { }
int a;
};

class ZONE1
{
public:
ZONE1 { }
int a;
};

class CZone : public ZONE, public ZONE1
{
public:
virtual void f { printf( "f\n"); return; }
};

int
main( )
{
CZone *c_zone = new CZone;

c_zone->f;

ZONE *zone = c_zone;
ZONE1 *zone1 = c_zone;
memset( zone, 0, sizeof(ZONE) + 1);
printf("aa\n");
c_zone->f;

printf( "%x\n", c_zone);
printf( "%x zone\n", zone);
printf( "%x zone1\n", zone1);
return 0;
}

во-вторых, если убрать упоминания о ZONE1, то будет ломаться, поскольку судя по всему, виртуальная таблица садится сразу после под-структур, а у нас стоит +1.
если убрать +1 из memset - то всё ок :)

Dasar

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

kokoc88

вообще-то меняется, да еще как, особенно в случаи множественного наследования.
Согласен, я не подумал про множественное наследование, потому что писал про конкретный случай CZone : ZONE.

kokoc88

во-первых, только что проверил, что при множественном наследовании меняется адрес при приведении:
У тебя там нету множественного наследования. Я всё-таки отвечал на твой пост.

Nqstya1710

У тебя там нету множественного наследования. Я всё-таки отвечал на твой пост.
прочитай ещё раз мой вопрос, свой ответ и ответ, который я тебе написал.
я не спрашивал, будет ли меняться указатель, но то, что при приведении он может меняться - это факт.
то, что при приведении в нашем случае ты можешь не париться о виртуальной таблице, где бы та ни была - это факт тоже.

kokoc88

я не спрашивал, будет ли меняться указатель, но то, что при приведении он может меняться - это факт.
то, что при приведении в нашем случае ты можешь не париться о виртуальной таблице, где бы та ни была - это факт тоже.
Что при приведении он может меняться мы уже выяснили. Кстати, что-то никто не отметил мою очевидную ошибку, что при приведении к POD он тоже может поменяться. Все написали про множественное наследование, о котором в постах не упоминалось.
Что при приведении в нашем случае мы можем о чём-то не заботиться - это не факт. Факт, что когда на работу выйдет нормальный программист, он несколько раз убьёт автотесты, пока не поймёт, какие мудаки с ним работают. :crazy:

Nqstya1710

Что при приведении он может меняться мы уже выяснили. Кстати, что-то никто не отметил мою очевидную ошибку, что при приведении к POD он тоже меняется. Все написали про множественное наследование, о котором в постах не упоминалось.
множественное наследование это хороший пример того, что затачиваться на то, где находится базовый класс, нельзя.

kokoc88

множественное наследование это хороший пример того, что затачиваться на то, где находится базовый класс, нельзя.
Ну тогда сам ответь на свой вопрос:
почему бы, в случае наследования, не сделать приведение типов, а потом memset?
Я уже ответил, просто фраза была построена неправильно - как обобщающее заявление. Я сказал, что ошибся. Тем не менее мой ответ остаётся правильным: если адрес не поменяется, то можно убить рабочий код. Тем более, что ситуация поменялся адрес или не поменялся может меняться при написании кода.

Nqstya1710

Что при приведении в нашем случае мы можем о чём-то не заботиться - это не факт. Факт, что когда на работу выйдет нормальный программист, он несколько раз убьёт автотесты, пока не поймёт, какие мудаки с ним работают. :crazy:
нормальный программист привык всё приводить через (void *) ? :)
то, что вообще ситуация с memset не очень красивая, я согласен. но я отвечал на вопрос. :)

kokoc88

нормальный программист привык всё приводить через (void *) ?
Нет. Скорее, он не привык к тому, что надо следить за тем, чтобы унаследованный POD оставался POD-ом. Вообще говоря, ситуация наследования от POD и добавление виртуальных методов может в некоторых случаях быть опасной даже без memset.
то, что вообще ситуация с memset не очень красивая, я согласен. но я отвечал на вопрос.
Ты не отвечал, ты его задал. :cool:

Nqstya1710

Я уже ответил, просто фраза была построена неправильно - как обобщающее заявление. Я сказал, что ошибся. Тем не менее мой ответ остаётся правильным: если адрес не поменяется, то можно убить рабочий код. Тем более, что ситуация поменялся адрес или не поменялся может меняться при написании кода.
блин, виртуальной таблицы у класса ZONE нет. потому если мы его затрём нулями при инициализации, то ничего не убьём.
где же виртуальная таблица с CZone? а меня уже это не интересует - поскольку я правильно сделал приведение типов.
хватит ругаться. :)

Nqstya1710

чтобы унаследованный POD оставался POD-ом
об этом я и написал с самого начала. наследование ради того, чтобы засунуть одну структуру в другую - это не совсем правильная вещь :)

kokoc88

блин, виртуальной таблицы у класса ZONE нет. потому если мы его затрём нулями при инициализации, то ничего не убьём.
где же виртуальная таблица с CZone? а меня уже это не интересует - поскольку я правильно сделал приведение типов.
В твоём конкретном примере всё будет работать, с этим никто не спорит. Всё дело в том, что компилятор нам ничего не гарантирует в данном случае. Я просто написал, что во время разработки эта ситуация может поменяться. Да и тема, которую мы обсуждаем, стоит или не стоит пользоваться memset для инициализации в C++. Поэтому все посты рассматриваются более-менее в этом свете.

Nqstya1710

Тем не менее мой ответ остаётся правильным: если адрес не поменяется, то можно убить рабочий код.
как раз таки ты ответил неверно. где адрес, нас не интересует. вопрос в том, остался ли класс ZONE подом. если вдруг кто-то в него всунул указатель на какую-то виртуальную таблицу, тогда будем ломаться.

kokoc88

как раз таки ты ответил неверно. где адрес, нас не интересует. вопрос в том, остался ли класс ZONE подом. если вдруг кто-то в него всунул указатель на какую-то виртуальную таблицу, тогда будем ломаться.
Я писал про адрес каста - меняется он или нет, неважно по какой причине: кроссплатформенная компиляция, рефакторинг, и т.п. Выше я уже отметил, что при касте к POD адрес меняется. И написал, что ситуация может измениться во время разработки.

erotic

Грех не влезть в разговор :p
Вопрос - на хрена вообще забивать все нулями? Чтобы думать, что все int'ы, size_t'ы и прочие равны нулю после создания объекта? Если ты забьешь int нулями, совсем не факт, что его логическое значение будет нулем, потому что возможны платформы, на которых логический ноль у int состоит не из всех нулевых бит.
P.S. Блин, из-за тебя сейчас сижу и думаю - как переслать double число с одного компа на другой, если у них double по-разному представляется? Не в строку же конвертить...

Dasar

Блин, из-за тебя сейчас сижу и думаю - как переслать double число с одного компа на другой, если у них double по-разному представляется? Не в строку же конвертить...
а на каких архитектурах 8-байтный double по разному кодируется?

erotic

Вопрос - на хрена вообще забивать все нулями? Чтобы думать, что все int'ы, size_t'ы и прочие равны нулю после создания объекта? Если ты забьешь int нулями, совсем не факт, что его логическое значение будет нулем, потому что возможны платформы, на которых логический ноль у int состоит не из всех нулевых бит.
Это я напиздел, конечно, int'ы, пожалуй, без проблем можно забивать нулями, т.к. memset сама принимает int. А вот забивать вещественные числа мб и не стоит. Но вообще тоже вопрос, в memset передается int, который там конвертится в char, которым уже и забивается память.

erotic

а на каких архитектурах 8-байтный double по разному кодируется?
А я без понятия. Но мне никто не говорил до этого, что он кодируется везде одинаково.

evolet

Если ты забьешь int нулями, совсем не факт, что его логическое значение будет нулем
Чувак, ну ты и отжигаешь
Я даже сначала подумал, что ты продолжаешь предыдущий трешак.
Я вот недавно узнал , что double можно физически забивать нулями (memset, например) и IEEE-... гарантируют, что это будет представлять 0.
имхо на практике, проблемы могут возникнуть только если на твоих платформах endian'ы не совпатают.

erotic

Чувак, ну ты и отжигаешьЯ даже сначала подумал, что ты продолжаешь предыдущий трешак.
Я же подумал, и исправился =)
По поводу double я не знал, что IEEE это гарантирует, но когда-то давно читал, что так делать может быть не переносимо.
Оставить комментарий
Имя или ник:
Комментарий: