![](https://forum.armkb.com/images/enlighten/misc/cat_top_ls.gif) |
vc bug - what's the cure??? |
![](https://forum.armkb.com/images/enlighten/misc/cat_top_rs.gif) |
28.07.2002, 22:10
|
#1
|
The Reloaded
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Rep Power: 5
|
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-ой ![Frown](https://forum.armkb.com/images/smilies/frown.gif) подсистема динамической памяти пытается найти соостветствующий адрес среди аллоцированных, и не находит
поделитесь опытом борьбы с этим багом
|
|
|
28.07.2002, 23:06
|
#2
|
Студент
Join Date: 06 2002
Location: Yerevan
Posts: 258
Rep Power: 0
|
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!
|
|
|
28.07.2002, 23:07
|
#3
|
Студент
Join Date: 06 2002
Location: Yerevan
Posts: 258
Rep Power: 0
|
Nu da zabyl pro obvious solution:
B1* b1 = ( B1* )( void* )new D;
|
|
|
28.07.2002, 23:11
|
#4
|
Студент
Join Date: 06 2002
Location: Yerevan
Posts: 258
Rep Power: 0
|
Mogesh' esche esli mazoxizma mnogo napisat' casting operator
|
|
|
28.07.2002, 23:16
|
#5
|
The Reloaded
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Rep Power: 5
|
Quote:
Originally posted by Eddi:
Nu da zabyl pro obvious solution:
B1* b1 = ( B1* )( void* )new D;
|
это не solution. такое эквивалентно reinterpret_cast-у, и на что после этого будет указывать b1? ведь это базовый указатель, и он должен корректно указывать на базовый подобъект в основном объекте, как и происходит безо всяких кастов.
|
|
|
28.07.2002, 23:20
|
#6
|
Студент
Join Date: 06 2002
Location: Yerevan
Posts: 258
Rep Power: 0
|
Daby dolgo ne perepinat'sya konkretnyj primer privedesh' plz, kogda eto ne budet rabotat'?
|
|
|
![](https://forum.armkb.com/images/enlighten/misc/cat_top_ls.gif) |
|
![](https://forum.armkb.com/images/enlighten/misc/cat_top_rs.gif) |
28.07.2002, 23:29
|
#7
|
The Reloaded
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Rep Power: 5
|
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 состоит из двух (в данном случае, а могло быть еще хуже ![Smilie](https://forum.armkb.com/images/smilies/smile.gif) ) подобъектов. один из них находится в самом начале D, и поэтому его адрес совпадает с адресом обрамляющего объекта. второй же - чуть ниже, и адрес у него не равен D::this (это конечно условная запись, не надо компилить ни в уме, ни на машине). при new подсистема динамической памяти регистрирует выделяемый адрес, чтобы потом освободить. в данном случае это адрес D-объекта. а освобождаю я потом через тот базовый указатель, который не совпадает с D::this. подсистема ищет B1::this в куче и, конечно же, не находит. и выбрасывает assert.
однако, на счастье всем интересующимся, я только что исправил положение. надо в обоих классах объявить виртуальные деструкторы (shame on me - в одном из них его не было! досаданая ошибка!). и тогда он добирается до корректного адреса при освобождении памяти (кстати, добирается именно через деструктор - объявление другой виртуальной функции с единственной целью - сгенерировать таблицу, не помогает)
|
|
|
![](https://forum.armkb.com/images/enlighten/misc/trans.gif) |
28.07.2002, 23:43
|
#8
|
The Reloaded
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Rep Power: 5
|
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 на самом деле находится по другому адерсу
|
|
|
28.07.2002, 23:47
|
#9
|
The Reloaded
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Rep Power: 5
|
bottom line: it wasn't a bug ![Wink](https://forum.armkb.com/images/smilies/wink.gif) just my fault. так что поучитесь на моей ошибке
|
|
|
28.07.2002, 23:54
|
#10
|
Студент
Join Date: 06 2002
Location: Yerevan
Posts: 258
Rep Power: 0
|
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 ![Frown](https://forum.armkb.com/images/smilies/frown.gif) ).
Just to have some more fun, another solution, without destructors:
delete (D*)b1;
|
|
|
28.07.2002, 23:59
|
#11
|
Студент
Join Date: 06 2002
Location: Yerevan
Posts: 258
Rep Power: 0
|
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
|
|
|
29.07.2002, 00:22
|
#12
|
The Reloaded
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Rep Power: 5
|
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-объекта.
|
|
|
29.07.2002, 00:25
|
#13
|
The Reloaded
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Rep Power: 5
|
Quote:
Originally posted by Eddi:
Just to have some more fun, another solution, without destructors:
delete (D*)b1;
|
это слишком частный случай, вряд ли полезный. ведь если известно, что это D, то зачем с ним работать как с B1? как раз код через базовые указатели используется, когда на этапе компиляции (и, следовательно, написания кода) точный тип в этой точке неизвестен. например, работа внутри функции, принявшей B1* параметр, или в контейнере, когда-то (в совершенно другой точке программы) принявшем базовые указатели, каждый из которых может указывать на один из n унаследованных объектов...
|
|
|
29.07.2002, 00:49
|
#14
|
Студент
Join Date: 06 2002
Location: Yerevan
Posts: 258
Rep Power: 0
|
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 ![Smilie](https://forum.armkb.com/images/smilies/smile.gif) 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 ![Smilie](https://forum.armkb.com/images/smilies/smile.gif) Just some fun
|
|
|
29.07.2002, 16:02
|
#15
|
The Reloaded
Join Date: 01 2002
Location: behind the flesh and gelatinе of soft dull eyes
Posts: 3,387
Rep Power: 5
|
Quote:
Originally posted by Eddi:
xochu primer!!
|
ну это уже демагогия. ничего, так уж и быть, сброшу примерчик, как только освобожусь. его построить нетрудно. только, чур, не говорить, что пример нежизненный и вымышленный.
|
|
|
All times are GMT. The time now is 02:27. |
|
|