1 / 1 / 0
Регистрация: 22.07.2014
Сообщений: 8
|
||||||||||||||||
1 | ||||||||||||||||
Оператор "delete" и ошибка "_BLOCK_TYPE_IS_VALID(pHead->nBlockUse) Error"22.07.2014, 22:14. Показов 5475. Ответов 9
Метки нет (Все метки)
Здравствуйте. Возникла проблема с оператором "delete". Пользуюсь VisualStudio 2010. Программа компилируется нормально. Все отрабатывает. Когда дело доходит до освобождения памяти, выделенной операцией "new", вылетает ошибка "_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)". Если закомментировать вызов "delete" - программа доходит до логического завершения. Очевидно, какая-то проблема с освобождением памяти. Если я выделяю память только на базовые объекты, "delete" нормально отрабатывает. Но при выделении памяти на любой унаследованный объект - вылетает вышеупомянутая ошибка. Похожая программа из книги по "С++", судя по словам автора книги, работает исправно. Вот код моей программы:
1) Заголовочный файл:
0
|
22.07.2014, 22:14 | |
Ответы с готовыми решениями:
9
При вызове delete[] _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) Ошибка pHead->nBlockUse Ошибка _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) При вызове деструктора выдается ошибка _BLOCK_TYPE_IS_VALID (pHead->nBlockUse) При вызове деструктора вылазит ошибка _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) |
20 / 20 / 3
Регистрация: 14.06.2012
Сообщений: 95
|
|
22.07.2014, 22:32 | 2 |
Вообще-то всё нормально, это распространённая ошибка MSVS. Где конкретно показывает ошибку, в стандартных файлах? решается переустановкой студии/перезапуском студии/рестарт винды/переход на новую версию студии
0
|
1 / 1 / 0
Регистрация: 22.07.2014
Сообщений: 8
|
|
22.07.2014, 23:00 [ТС] | 3 |
Я не совсем понял ваш вопрос. Вот скриншот ошибки:
Возможно он подтолкнет вас на какую-нибудь мысль.
0
|
Ушел с форума
|
|
22.07.2014, 23:24 | 4 |
Стыдно должно быть писать такую ересь.
Про виртуальный деструктор никогда не слышали ? А теперь нажмите "Retry" и окажетесь в отладчике, с call stack, переменными и т.д. У этого автора весьма своеобразное представление о том, что такое C++.
0
|
20 / 20 / 3
Регистрация: 14.06.2012
Сообщений: 95
|
||||||
22.07.2014, 23:26 | 5 | |||||
Ага, и что порой код
0
|
1 / 1 / 0
Регистрация: 22.07.2014
Сообщений: 8
|
|
22.07.2014, 23:38 [ТС] | 6 |
Спасибо за идею. Сделал деструктор виртуальным и все заработало. Я совсем забыл про него.
Добавлено через 5 минут IIARTEMII, вам тоже спасибо за помощь.
0
|
Ушел с форума
|
||||||
22.07.2014, 23:40 | 7 | |||||
IIARTEMII, какой плохой компилятор этот Microsoft Visual C++ !
А между тем, полиморфное удаление объекта без виртуального деструктора - UB.
1
|
20 / 20 / 3
Регистрация: 14.06.2012
Сообщений: 95
|
||||||
22.07.2014, 23:50 | 8 | |||||
Это всё понятно
Теперь у меня вопрос, чтобы не создавать новую тему: Что это за механизм такой, который реагирует на отсутствие виртуального деструктора, если по сути это приводит к утечке памяти, а не к программной ошибке (да, UB может привести к ошибке, а может и нет, но...)? Почему этот механизм себя проявляет только в MSVS? В других продуктах такого никогда не видел Ведь если у нас есть базовый класс, есть унаследованный от него дочерний:
Если схематично представить память, то: |- - - - Base - - - -| - - Der - - | при подходе выше, у нас будет: | - - - - - - - - - - | - - Der - - | Почему тут ошибка? Или тут немножко всё не так?
0
|
Ушел с форума
|
||||||||||||||||||||||||||
23.07.2014, 01:53 | 9 | |||||||||||||||||||||||||
Тут очень многое зависит от деталей реализации - от того, как сделаны
виртуальные таблицы в данном конкретном компиляторе и как устроен его аллокатор памяти. Приключения начинаются вот в этой строке:
включая деструктор, то при касте указателя Der к Base его скалярное значение сохранится. То есть, к примеру, если "new Der" вернет адрес 0xABCDE8, то и в ptr будет записано 0xABCDE8. В этом случае, когда будет вызван "delete ptr", аллокатор получит все тот же адрес и сможет корректно освободить занимаемую объектом Der память. Хотя деструктор Der вызван не будет. Предположим, Der унаследован не только от Base, но еще и от Megabase, причем Megabase в списке наследования расположен раньше Base:
изменению его скалярного значения. Пример:
освобождения памяти по адресу 0x985043c, хотя при создании объекта Der был возвращен адрес 0x9850438. Это равноценно тому, что в delete передали адрес, который никогда не выделялся. Кстати, возникновение ошибки в данном примере характерно не только для MS Visual C++, можете проверить на любом компиляторе, который есть под рукой. Нечто похожее происходит и при виртуальном наследовании, так как там "раскладка" классов в памяти заметно отличается от обычной, хотя все это, повторюсь, очень compiler-specific:
При обычном (невиртуальном) наследовании все было бы наоборот. И последний пример, снова с изменением скалярного значения указателя при касте к базовому классу:
деструктор, аллокатор всегда получает "правильный" адрес памяти для очистки, так что проблем, описанных выше, не возникает.
2
|
327 / 230 / 55
Регистрация: 30.05.2014
Сообщений: 682
|
|
23.07.2014, 04:32 | 10 |
Поднимаем глаза и читаем заголовок окна сообщения.
Механизм этот называется MS CRT Debug Library. При правильном применении очень полезный мехнизм, в том числе и для обнаружения утечек памяти. http://msdn.microsoft.com/en-u... tc9t1.aspx http://msdn.microsoft.com/en-u... 80%29.aspx
0
|
23.07.2014, 04:32 | |
23.07.2014, 04:32 | |
Помогаю со студенческими работами здесь
10
Ошибка при запуске программы. _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) При освобождении памяти от указателей на массивы вылетает ошибка: _BLOCK_TYPE_IS_VALID(phead->nBlockUse) phead->nblockuse _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |