Armenian Knowledge Base  

Go Back   Armenian Knowledge Base > Technical sections > Languages, Compilers, Interpreters
Register

Reply
 
LinkBack Thread Tools
Old 28.07.2002, 23:10   #1
The Reloaded
 
Aram Hambardzumyan's Avatar
 
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Downloads: 4
Uploads: 0
Reputation: 146 | 4
Post vc bug - what's the cure???

вот код:
Code:
struct B1 { };	

struct B2 { };	

struct D: B2, B1 { };

int main()
{
	B1* b1 = new D;
	delete b1;

	B2* b2 = new D;
	delete b2;

	return 0;
}
код иллюстрирует очередной баг ms-компилера. суть: при динамическом создании объекта с двойным наследованием он не может правильно удалить его. программа вылетает при попытке стереть по одному из базовомых указателей, который не совпадает с указателем на весь объект (в зависимости от того, в каком порядке B1 и B2 стоят в списке базовых классов, вылетает при стирании либо через B1*, либо B2*). и это не только в 6-ой версии, но и в 7-ой подсистема динамической памяти пытается найти соостветствующий адрес среди аллоцированных, и не находит
поделитесь опытом борьбы с этим багом
Reply With Quote
Old 29.07.2002, 00:06   #2
Студент
 
Join Date: 06 2002
Location: Yerevan
Posts: 258
Downloads: 0
Uploads: 0
Reputation: 0 | 0
Post

Ok, just some info that may help.

Debug pokazal, chto oshibka ne v new ili delete-e, a v operatore = (tochnee v casting operatore), posle new on poluchaet pravil'nyj address, no kogda = delaet, pribavlyaet k addressu odin byte (ochevidno eto kak-to svyazanno s tem chto on na vtorom meste v nasledovanii) i vse letit kuda podal'she.

Oshibka ochen' weird, esli najdesh' solution, obyazatel'no postni!
__________________
http://www.d-brane.com
Reply With Quote
Old 29.07.2002, 00:07   #3
Студент
 
Join Date: 06 2002
Location: Yerevan
Posts: 258
Downloads: 0
Uploads: 0
Reputation: 0 | 0
Post

Nu da zabyl pro obvious solution:

B1* b1 = ( B1* )( void* )new D;
Reply With Quote
Old 29.07.2002, 00:11   #4
Студент
 
Join Date: 06 2002
Location: Yerevan
Posts: 258
Downloads: 0
Uploads: 0
Reputation: 0 | 0
Post

Mogesh' esche esli mazoxizma mnogo napisat' casting operator
Reply With Quote
Old 29.07.2002, 00:16   #5
The Reloaded
 
Aram Hambardzumyan's Avatar
 
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Downloads: 4
Uploads: 0
Reputation: 146 | 4
Post

Quote:
Originally posted by Eddi:
Nu da zabyl pro obvious solution:

B1* b1 = ( B1* )( void* )new D;
это не solution. такое эквивалентно reinterpret_cast-у, и на что после этого будет указывать b1? ведь это базовый указатель, и он должен корректно указывать на базовый подобъект в основном объекте, как и происходит безо всяких кастов.
Reply With Quote
Old 29.07.2002, 00:20   #6
Студент
 
Join Date: 06 2002
Location: Yerevan
Posts: 258
Downloads: 0
Uploads: 0
Reputation: 0 | 0
Post

Daby dolgo ne perepinat'sya konkretnyj primer privedesh' plz, kogda eto ne budet rabotat'?
Reply With Quote
Old 29.07.2002, 00:29   #7
The Reloaded
 
Aram Hambardzumyan's Avatar
 
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Downloads: 4
Uploads: 0
Reputation: 146 | 4
Post

Quote:
Originally posted by Eddi:
Debug pokazal, chto oshibka ne v new ili delete-e, a v operatore = (tochnee v casting operatore), posle new on poluchaet pravil'nyj address, no kogda = delaet, pribavlyaet k addressu odin byte (ochevidno eto kak-to svyazanno s tem chto on na vtorom meste v nasledovanii) i vse letit kuda podal'she.
вот что и для чего на самом деле происходит. объект D состоит из двух (в данном случае, а могло быть еще хуже ) подобъектов. один из них находится в самом начале D, и поэтому его адрес совпадает с адресом обрамляющего объекта. второй же - чуть ниже, и адрес у него не равен D::this (это конечно условная запись, не надо компилить ни в уме, ни на машине). при new подсистема динамической памяти регистрирует выделяемый адрес, чтобы потом освободить. в данном случае это адрес D-объекта. а освобождаю я потом через тот базовый указатель, который не совпадает с D::this. подсистема ищет B1::this в куче и, конечно же, не находит. и выбрасывает assert.
однако, на счастье всем интересующимся, я только что исправил положение. надо в обоих классах объявить виртуальные деструкторы (shame on me - в одном из них его не было! досаданая ошибка!). и тогда он добирается до корректного адреса при освобождении памяти (кстати, добирается именно через деструктор - объявление другой виртуальной функции с единственной целью - сгенерировать таблицу, не помогает)
Reply With Quote
Old 29.07.2002, 00:43   #8
The Reloaded
 
Aram Hambardzumyan's Avatar
 
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Downloads: 4
Uploads: 0
Reputation: 146 | 4
Post

Quote:
Originally posted by Eddi:
Daby dolgo ne perepinat'sya konkretnyj primer privedesh' plz, kogda eto ne budet rabotat'?
пожалуйста (fout - мой поток, который делает вывод в cout, добавляя endl):
Code:
struct B1 { };	
struct B2 { };	
struct D: B2, B1 { };

int main()
{
	D* d = new D;
	b1 = (B1*)(void*)d; fout << b1;
	b1 = d;             fout << b1;
	                    fout << d;

	delete d;

	return 0;
}
а вот выход этого примера:
002F0998
002F099C
002F0998
как видим, во втором и первом случае содержимые b1 различаются. в первом случае этот адрес совпадает с третьим случаем, т. е. b1 указывает ровно на d, хотя, как следует из второго случая, подобъект B1 на самом деле находится по другому адерсу
Reply With Quote
Old 29.07.2002, 00:47   #9
The Reloaded
 
Aram Hambardzumyan's Avatar
 
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Downloads: 4
Uploads: 0
Reputation: 146 | 4
Post

bottom line: it wasn't a bug just my fault. так что поучитесь на моей ошибке
Reply With Quote
Old 29.07.2002, 00:54   #10
Студент
 
Join Date: 06 2002
Location: Yerevan
Posts: 258
Downloads: 0
Uploads: 0
Reputation: 0 | 0
Post

Ok, good

Kogda compile delaesh' s virtual destructorami delaet delete sovershenno po-drugomu (dage ne zaxodit v delete, at least v c-code mode-e ).

Just to have some more fun, another solution, without destructors:

delete (D*)b1;

Reply With Quote
Old 29.07.2002, 00:59   #11
Студент
 
Join Date: 06 2002
Location: Yerevan
Posts: 258
Downloads: 0
Uploads: 0
Reputation: 0 | 0
Post

btw s primerom tvoim ne slishkom soglasen
T.e. on ne pokazal chto-to nevernoe, on prosto pokazal, chto razlichnye address-a, ok so what, moget/budet li ot etogo chto-libo menyatsya pri ispol'zovanii etogo ob'ekta?

P.S. Ya ne govoryu chto ty ne prav, prosto esli state delaesh', dokagi
Reply With Quote
Old 29.07.2002, 01:22   #12
The Reloaded
 
Aram Hambardzumyan's Avatar
 
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Downloads: 4
Uploads: 0
Reputation: 146 | 4
Post

Quote:
Originally posted by Eddi:
btw s primerom tvoim ne slishkom soglasen
T.e. on ne pokazal chto-to nevernoe, on prosto pokazal, chto razlichnye address-a, ok so what, moget/budet li ot etogo chto-libo menyatsya pri ispol'zovanii etogo ob'ekta?
конечно будет - под b1 подразуемвяается объект B1, со своей внутренней консистентностью. а в примере с таким приведением типов работаем с указателем как с B1, но на область памяти , которая не инициализировалась как B1. а это не только не имеет смысла, но и просто может приводить к сбоям. в частности, в данном случае - непредсказуемо нарушая состояние D-объекта.
Reply With Quote
Old 29.07.2002, 01:25   #13
The Reloaded
 
Aram Hambardzumyan's Avatar
 
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Downloads: 4
Uploads: 0
Reputation: 146 | 4
Post

Quote:
Originally posted by Eddi:
Just to have some more fun, another solution, without destructors:

delete (D*)b1;
это слишком частный случай, вряд ли полезный. ведь если известно, что это D, то зачем с ним работать как с B1? как раз код через базовые указатели используется, когда на этапе компиляции (и, следовательно, написания кода) точный тип в этой точке неизвестен. например, работа внутри функции, принявшей B1* параметр, или в контейнере, когда-то (в совершенно другой точке программы) принявшем базовые указатели, каждый из которых может указывать на один из n унаследованных объектов...
Reply With Quote
Old 29.07.2002, 01:49   #14
Студент
 
Join Date: 06 2002
Location: Yerevan
Posts: 258
Downloads: 0
Uploads: 0
Reputation: 0 | 0
Post

Quote:
Originally posted by Aram Hambardzumyan:
Quote:
Originally posted by Eddi:
btw s primerom tvoim ne slishkom soglasen
T.e. on ne pokazal chto-to nevernoe, on prosto pokazal, chto razlichnye address-a, ok so what, moget/budet li ot etogo chto-libo menyatsya pri ispol'zovanii etogo ob'ekta?
конечно будет - под b1 подразуемвяается объект B1, со своей внутренней консистентностью. а в примере с таким приведением типов работаем с указателем как с B1, но на область памяти , которая не инициализировалась как B1. а это не только не имеет смысла, но и просто может приводить к сбоям. в частности, в данном случае - непредсказуемо нарушая состояние D-объекта.
Strongly disagree T.k. real'no new vozvraschaet imenno to chto ty vidish' cherez (void*) new D, tak chto xochu primer!!

A naschet chastnogo primera totally agree Just some fun
Reply With Quote
Old 29.07.2002, 17:02   #15
The Reloaded
 
Aram Hambardzumyan's Avatar
 
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Downloads: 4
Uploads: 0
Reputation: 146 | 4
Post

Quote:
Originally posted by Eddi:
xochu primer!!
ну это уже демагогия. ничего, так уж и быть, сброшу примерчик, как только освобожусь. его построить нетрудно. только, чур, не говорить, что пример нежизненный и вымышленный.
Reply With Quote
Sponsored Links
Reply

Thread Tools


На правах рекламы:
реклама

All times are GMT. The time now is 20:50.


Powered by vBulletin® Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.