Почему срок жизни объекта заканчивается перед выполнением нетривиального деструктора? [Дубликат]

Проблема заключается в том, что buffer живет в стеке и выходит за пределы области действия с момента выхода recvmsg.

Вы можете выделить buffer в куче:

char *recvmsg(){
  char *buffer = malloc(1024);
  return buffer;
}
]

Обратите внимание, что теперь вызывающий абонент отвечает за распоряжение выделенной памятью:

void main(){
  char *reply = recvmsg();
  free(reply);
}
11
задан bdonlan 23 December 2011 в 03:50
поделиться

4 ответа

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

8
ответ дан Andrew White 18 August 2018 в 07:27
поделиться
  • 1
    Что вы подразумеваете под потребляющим объектом ? – Pubby 23 December 2011 в 04:00
  • 2
    Любой объект, который использует целевой класс. Если вы пишете класс, который использует строку, то ваш класс является потребителем строки. – Andrew White 23 December 2011 в 04:02
  • 3
    – fredoverflow 23 December 2011 в 04:19
  • 4
    Это неверно. Время жизни актуально для самого объекта; например это связано с тем, как виртуальные функции решаются внутри деструктора. & Quot; срок службы & Quot; является конкретным термином в стандарте со специфическим значением и последствиями, и это не означает, что «потребительский класс не должен пытаться обращаться к членам объекта после начала уничтожения». Хорошо вызывать методы, пока деструктор продолжается, if класс поддерживает его. Я бы рекомендовал не предполагать, что класс поддерживает его, если только не задокументировано! – ech 12 January 2017 в 19:17
  • 5
    Прошло много времени с тех пор, как я просмотрел спецификацию (или этот ответ), поэтому вы вполне можете быть прав. У вас есть ссылка на ваш вопрос о том, что это «конкретный термин». – Andrew White 12 January 2017 в 22:09

Если время жизни заканчивается до начала деструктора, не означает ли это, что доступ к членам в деструкторе является неопределенным поведением?

Надеюсь, нет:

От N3242 Конструкция и уничтожение [class.cdtor] / 3

Чтобы сформировать указатель на (или получить доступ к значению) прямой нестатический член объекта obj, построение obj должно и его уничтожение не будет завершено, в противном случае вычисление значения указателя (или доступа к значению члена) приведет к неопределенному поведению.

7
ответ дан curiousguy 18 August 2018 в 07:27
поделиться
  • 1
    Этот ответ абсолютно неверен! И все же удалось получить 6 upvotes. SO не работает. – curiousguy 31 May 2012 в 05:28
  • 2
    почему вы его не удалили? – David Rodríguez - dribeas 14 August 2012 в 05:24
  • 3
    @ DavidRodríguez-dribeas Ответ не отвечает на вопрос юриста, но очень ясно что-то доказывает. – curiousguy 14 August 2012 в 05:38
  • 4
    Ответ правильный, поскольку он говорит, что это не UB, по крайней мере. И он не говорит ничего неправильного, что делает его потрясающе хорошим ответом по сравнению с другими здесь. – ech 12 January 2017 в 19:21

«Lifetime» не означает этого. Это точно определенный термин в стандарте, который имеет множество последствий, но он может не иметь всех последствий, которые вы могли бы подумать. Члены могут по-прежнему использоваться во время строительства и уничтожения, внешний код может вызывать функции-члены и т. Д. И т. Д.

. Конечно, для клиентского кода немного странно вызывать функции-члены одновременно с деструктором, но не неслыханно и, конечно же, не запрещается языком. В частности, std::condition_variable явно разрешает вызов деструктора, пока есть нерешенные вызовы condition_variable::wait(). Он запрещает новые вызовы wait() после запуска деструктора.

1
ответ дан ech 18 August 2018 в 07:27
поделиться

Нет, нет проблем:

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

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

5
ответ дан Kerrek SB 18 August 2018 в 07:27
поделиться
  • 1
    Означает ли это, что это будет недействительным ?: constructor() { outside_function(this); } (может также быть деструктором) – Pubby 23 December 2011 в 04:11
  • 2
    @Pubby: Вы должны быть очень осторожны с тем, что вы делаете с this в конструкторе и деструкторе, поскольку он не указывает на живой объект. В принципе, «не использовать» & quot; применяется. Хранение указателя в порядке, но ссылаться на потенциальный объект - нет. – Kerrek SB 23 December 2011 в 04:16
  • 3
    Но как вы можете получить доступ к элементам без использования this (при условии, что он неявно добавлен)? constructor() { this->x = 0; this->mfun(); } – Pubby 23 December 2011 в 04:19
  • 4
    @Pubby есть специальные правила, когда вы тоже в конструкторе, потому что экземпляр не «полностью жив», еще - например, что mfun () в этом & gt; mfun () не может быть виртуальным. – kfmfe04 23 December 2011 в 04:42
  • 5
    @Pubby: конструктор может ссылаться на объекты-члены (и, таким образом, использовать this ", если хотите). То, что конструктор не должен делать, это вызвать внешнюю функцию foo(*this), которая ожидает объект (полностью построенный). – Kerrek SB 23 December 2011 в 12:16
Другие вопросы по тегам:

Похожие вопросы: