Пожалуйста, обратите внимание, что я не хочу, чтобы решить любую проблему с моим вопросом - я думал о вероятностях вещей, чтобы случиться и, таким образом, было интересно, о чем-то:Что именно происходит, если вы удаляете объект? (НКУ) (При двойном удаления аварии?)
Что именно происходит, если вы удаляете объект и используете gcc как компилятор?
На прошлой неделе я исследовал сбой, когда состояние гонки привело к двойному удалению объекта.
Авария произошла при вызове виртуального деструктора объекта, поскольку указатель на таблицу виртуальных функций уже был перезаписан.
Является ли указатель виртуальной функции перезаписанным первым удалением?
Если нет, то это второй безопасный сейф, если пока не будет выделено новое распределение памяти?
Мне интересно, почему проблема была у меня не была распознана раньше, и единственное исключение состоит в том, что либо таблица виртуальных функций перезаписывается немедленно во время первого удаления, либо второе удаление не вылетает.
(Первое означает, что авария всегда происходит в том же месте, если происходит «гонка» - вторая, что обычно не происходит, когда происходит гонка - и только если третий поток перезаписывает объект удаления в Тем временем проблема возникает)
Edit/Update:.
Я сделал тест, следующий код падает с Segfault (НКУ 4,4, i686 и amd64):
class M
{
private:
int* ptr;
public:
M() {
ptr = new int[1];
}
virtual ~M() {delete ptr;}
};
int main(int argc, char** argv)
{
M* ptr = new M();
delete ptr;
delete ptr;
}
Если я удалю «виртуальный» из dtor, программа будет прервана glibc, потому что она обнаруживает двойное освобождение. При «виртуальном» сбое происходит при вызове косвенной функции деструктору, поскольку указатель на таблицу виртуальных функций недействителен.
На обоих моделях amd64 и i686 указатель указывает на допустимую область памяти (кучу), но значение недействительно (счетчик? Очень низкий, например, 0x11 или 0x21), поэтому «вызов» (или «jmp» «когда компилятор выполнил оптимизацию возврата) переходит к недопустимой области.
Программа получила сигнал SIGSEGV,
ошибку сегментации. 0x0000000000000021
in ??() (gdb)
#
0 0x0000000000000021 in ??()
#
1 0x000000000040083e в главной()
Так с вышеуказанными условиями, указатель на таблицу виртуальных функций ВСЕГДА перезаписаны первым удалить, поэтому следующий удаление будет переходить к нирване, если класс имеет виртуальный деструктор.
Похоже, вам нужно вкладывать деньги в какой-то мьютекса или критические секции слишком – 2010-08-01 01:25:49
0A0D: Это мое решение prelimary (обходной путь). На самом деле был дефект дизайна, потому что не было намерения, что есть два потока, которые могут удалить объект. – IanH