LINUX.ORG.RU

В каком порядке вызываются деструкторы объектов при разрушении кадра стека?

 ,


0

4

Вот есть код

#include <stdio.h>

struct A{
	int x;
	~A(){ printf("%d\n", x); }
};

int main(int argc, const char **argv){
	A a1; a1.x = 1;
	A a2; a2.x = 2;
	return 0;
}
Всегда ли будет вывод
2
1
это гарантируется стандартом?

★★★★★
Ответ на: комментарий от peregrine

А при чём тут компиляторы сишки. Я говорил не про использование одного и того же определения в C/C++-хедере, а про plain old data.

(Хотя, вероятно, вертухай говорил как раз про использование одних и тех же хедеров, а я ответил нерелевантную чушь, да.)

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от Dudraug

Есть нормальный boost format. Хотя потоки в 99% случаев вполне юзабельные вполне нормальные и зачастую лучше лапши-бомбы замедленного действия вида:

char a[256] = "";
int i = 0;
scanf("%s %d", &a, &i);

// а потом еще:
snprintf(a, 256, "blah blah %s", someStringWhichIsLongerThen256);

Если тебя так беспокоят потоки в stl, то за пару часов можно написать свой велосипед а-ля boost format (если не хочется его тащить) и использовать его всю жизнь везде.

invy ★★★★★
()
Последнее исправление: invy (всего исправлений: 1)
Ответ на: комментарий от matrixd

class обычно используют, когда есть инварианты (грубо говоря, не любое сочетание элементов данных является допустимым). struct обычно используют, когда нет инвариантов. Это просто соглашение, достаточно распространённое.

quoob
()
Ответ на: комментарий от invy

Вынужден отметить, что «бомба замедленного действия» в твоём примере тривиальным образом избегается, если немного читнуть манцов и не быдлокодить.

Я тоже не люблю C-style в плюсах, но сишный инструментарий formatted I/O банально лучше плюсового.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Это уже быдлокодом называется. Вместо того, чтобы взять boost format или написать свой человеческий format, если религия не позволяет (это делается один раз в жизни и занимает несколько часов) ты предлагаешь лячкать какие-то костыли и нагромождения с совершенно непригодными для этого конструкциями?

invy ★★★★★
()
Ответ на: комментарий от invy

Вместо того, чтобы взять boost format

Ну да, давайте тащить boost ради того, чтобы перевести число в строку (для чего, кстати, хватит локальной переменной типа char[]).

или написать свой человеческий format

То же самое.

tailgunner ★★★★★
()
Ответ на: комментарий от invy

Boost format — хорошо, да. Но мы тут сравнивали стандартные средства. И я не вижу никаких костылей в том, чтобы взять unique_ptr, обернуть его кастомным аллокатором и засунуть в него указатель, возвращённый из scanf(«%ms»)/asprintf().

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

И я не вижу никаких костылей в том, чтобы взять unique_ptr, обернуть его кастомным аллокатором и засунуть в него указатель, возвращённый из scanf(«%ms»)/asprintf().

А теперь сам прочти то что ты написал еще раз и подумай, о том, точно ли ты тут костылей не видишь? :))))

Не, даже так:

intelfx ★★★★★ (15.02.2016 22:57:40) И я не вижу никаких костылей в том, чтобы взять unique_ptr, обернуть его кастомным аллокатором и засунуть в него указатель, возвращённый из scanf(«%ms»)/asprintf().

invy ★★★★★
()
Последнее исправление: invy (всего исправлений: 3)
Ответ на: комментарий от tailgunner

Ну да, давайте тащить boost ради того, чтобы перевести число в строку (для чего, кстати, хватит локальной переменной типа char[]).

Для того чтобы «перевести число в строку» один раз на тыщу строк, у тебя руки не отсохнут, если напишешь даже stringstream;

То же самое.

Тебе жалко #include «string_format.h» сделать? :)

invy ★★★★★
()
Ответ на: комментарий от invy

Для того чтобы «перевести число в строку» один раз на тыщу строк, у тебя руки не отсохнут, если напишешь даже stringstream;

Не отсохнут, конечно, но мне будет приятно думать, что я избежал динамического выделения памяти и достиг exception safety без RAII :)

Тебе жалко #include «string_format.h» сделать? :)

Мне жалко писать сам string_format.h (если его еще нет).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Ну да, давайте тащить boost ради того, чтобы перевести число в строку (для чего, кстати, хватит локальной переменной типа char[]).

Почему бы и нет?

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

тащить boost ради того, чтобы перевести число в строку (для чего, кстати, хватит локальной переменной типа char[]).

Почему бы и нет?

Вопрос соотношения затрат и выгод. Не говоря о том, что на целевой машине boost может не быть.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Не говоря о том, что на целевой машине boost может не быть.

Целевая - это какая? Девелоперская или билд-сервер? Там будет всё, что надо.

DarkEld3r ★★★★★
()

Всегда ли будет вывод ?

в приведённом случае - а вот и невсегда :-) При оптимизации компилятору мешает удалить(просто не размещать) оба экземпляра разве что вызов printf в деструкторах. Если как-то пояснить компилеру что printf - pure, то может даже не быть ничего.

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

MKuznetsov ★★★★★
()
Ответ на: комментарий от MKuznetsov

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

Вот так ррраз... и вся библия нафиг.

tailgunner ★★★★★
()
Ответ на: комментарий от MKuznetsov

Потому как размещением и порядком инициализации независимых объектов должен ведать компилер.

Мне казалось что компайлер вообще всем ведает... но хороший компайлер при этом еще следует стандарту.

AIv ★★★★★
() автор топика
Ответ на: комментарий от DarkEld3r

У меня каждый раз при развраичвании кода на сторонней машине возникает список неразрешенных зависимостей. Там чего только нету...

AIv ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Не отсохнут, конечно, но мне будет приятно думать, что я избежал динамического выделения памяти и достиг exception safety без RAII :)

Но получил потенциальные проблемы в виде обрубания строки, либо потенциальные утечки памяти и вообще char* - не кошерно.

Мне жалко писать сам string_format.h (если его еще нет).

Т.е. ты не удосужился обернуть scanf и printf во что-то человеческое и продолжаешь заниматься кодо-дубликацией? :)
Ох уж эти ctrl+c - ctrl+v программисты :)

invy ★★★★★
()
Ответ на: комментарий от invy

Дяденька, а я тоже sprintf-ом пользуюсь, только он у меня пишет в кольцевой буфер ну и из обертки ес-но.

Обрубание строки меня не волнует.

AIv ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

Ну да, давайте тащить boost ради того, чтобы перевести число в строку (для чего, кстати, хватит локальной переменной типа char[]).

Мисье знал, что половина буста это хидер-онли библиотека? И что есть bcp позволяющий запилить свой буст с блэк джеком и шлюхами Только с тем что нужно

Dudraug ★★★★★
()
Ответ на: комментарий от tailgunner

У меня есть все основания считать иначе.

Буст можно поставлять прямо с исходниками и собирать вместе с проектом. Мы на проекте так делаем.

Dudraug ★★★★★
()
Ответ на: комментарий от Dudraug

Мисье знал, что половина буста это хидер-онли библиотека?

Представь, не только ты знаешь общеизвестные вещи.

Буст можно поставлять прямо с исходниками и собирать вместе с проектом.

И это я тоже знаю. Речь о том, что если в проекте нет Boost, то вкрячивать его для простого форматного преобразования глупо.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от invy

получил потенциальные проблемы в виде обрубания строки

От преобразования числа в строку? Нет. И даже для печати %s может быть известна максимальная длина строки.

либо потенциальные утечки памяти и вообще char* - не кошерно

Я же написал - char[]

Т.е. ты не удосужился обернуть scanf и printf во что-то человеческое и продолжаешь заниматься кодо-дубликацией? :)

Дупликацией какого кода?

Ох уж эти ctrl+c - ctrl+v программисты :)

Мне кажется, у тебя телепатор сломался.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Речь о том, что если в проекте нет Boost, то вкрячивать его для простого форматного преобразования глупо.

После bcp скорее всего там будет совсем мало буста. А это и не страшно. То есть по сути ты вкорчишь лишь boost format. А там глядишь и остальное из буста пригодится.

Dudraug ★★★★★
()
Ответ на: комментарий от Dudraug

После bcp скорее всего там будет совсем мало буста.

Совсем мало - это сколько? Я как-то вырезал Boost.Variant - получилось over 5Mbytes кода. Легче оказалось написать свой sum type.

tailgunner ★★★★★
()
Ответ на: комментарий от AIv

с точностью до прав доступа по умолчанию.

лол, что?

anonymous
()
Ответ на: комментарий от anonymous

тред не читал

уже написали про вторую разницу: структуры в стеке, объекты в куче (если через new), деструктор не виртуальный то есть по факту, статический метод класса/статический метод/инлайнится

?

anonymous
()
Ответ на: тред не читал от anonymous

структуры в стеке, объекты в куче (если через new)

ЩИТО?

Dudraug ★★★★★
()
Ответ на: комментарий от AIv

Обрубание строки меня не волнует.

А потом думаешь, почему вдруг у тебя в логе «The program at: /home/username/... was not prop».

Либо смотришь, статический анализатор ругается на что-то вроде «char[100500] может переполнить стэк.», открываешь... а там sprintfы.

invy ★★★★★
()
Ответ на: комментарий от tailgunner

От преобразования числа в строку? Нет. И даже для печати %s может быть известна максимальная длина строки.
Я же написал - char[]

char a[256] = "";
snprintf(a, 256, "blah blah %s", someStringWhichIsLongerThan256);

Что тут будешь делать?

Дупликацией какого кода?

Да хотя бы char[] эксклюзивно для sprintf/scanf.

invy ★★★★★
()
Последнее исправление: invy (всего исправлений: 1)
Ответ на: комментарий от invy

Не, у меня в логе все норм.

AIv ★★★★★
() автор топика
Ответ на: комментарий от invy

snprintf(a, 256, «blah blah %s», someStringWhichIsLongerThan256);
Что тут будешь делать?

Зависит от того, почему some_string_is_longer_than_256. Если входной контроль прохлопал - поправлю его. Если максимальная длина в принципе неизвестна - да, snprintf лучше не использовать. Но ты приводишь этот пример со строкой неограниченной длины как основание запрета на использование форматного вывода (и ввода) вообще.

Дупликацией какого кода?

Да хотя бы char[]

ЯННП. char[] - это данные.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Если максимальная длина в принципе неизвестна

Она в принципе почти всегда не известна. Что хуже, она может внезапно вырасти в спецификациях, а в твоем коде (который ты написал пару лет назад), внезапно - нет. Потому надо исходить из того что она всегда неизвестна.

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

Только как запрет на использование форматного ввода и вывода из C-шного рантайма. boost format, cppformat и прочие - только за.

ЯННП. char[] - это данные.

char[] в контексте форматного ввода/вывода - лишняя сущность.

invy ★★★★★
()
Последнее исправление: invy (всего исправлений: 1)
Ответ на: комментарий от invy

Только как запрет на использование форматного ввода и вывода из C-шного рантайма. boost format, cppformat и прочие - только за.

О кстати... а как насчет такого маленького шедевра?

class membuf : public basic_streambuf<char>
{
public:
  membuf(char* p, size_t n) {
    setg(p, p, p + n);
    setp(p, p + n);
  }
}

string foo(int v)
{
  char buf[40];
  membuf b(buf, sizeof(buf));
  ostream o(&b);

  o << v;
  return string(buf);
}

%)

something to consider

Это всё круто, если нет ограничений на то, что тащишь в проект.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

О кстати... а как насчет такого маленького шедевра?

ССЗБ разные бывают.

Это всё круто, если нет ограничений на то, что тащишь в проект.

Это аргумент, почему таки стоит пересмотреть то, что надо тащить в проект а что - нет.

invy ★★★★★
()
Ответ на: комментарий от invy

О кстати... а как насчет такого маленького шедевра?

ССЗБ разные бывают.

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

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

маленький

в моем представлении маленький - одна строка, например return to_string(v);

char buf[40];

Почему не 42?
buf за пределами membuf.
buf не инициализирован, а следовательно не null-терминирован. Ожидаю крэша string(buf)

invy ★★★★★
()
Ответ на: комментарий от invy

в моем представлении маленький - одна строка, например return to_string(v);

Это реализация to_string для компилятора, где его нет стандартно.

buf не инициализирован, а следовательно не null-терминирован. Ожидаю крэша string(buf)

Point taken.

tailgunner ★★★★★
()
Ответ на: комментарий от Dudraug

Серьёзно. Если нет нужды в чём-то специфическом, то стримы гораздо удобнее. Вообще по мне одна из лучших фич плюсов.

peregrine ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.