Форум программистов, компьютерный форум CyberForum.ru

Оператор "delete" и ошибка "_BLOCK_TYPE_IS_VALID(pHead->nBlockUse) Error" - C++

Восстановить пароль Регистрация
Другие темы раздела
C++ Параллельный set_difference http://www.cyberforum.ru/cpp-beginners/thread1232255.html
Как лучше оформить на C++ такую задачу?
C++ Как сделать ровный вывод состояния регистров Всем исключительно доброго времени дня или ночи. Я начинающий, так что прошу сильно меня не пинать. В общем, вот в чём дело: По заданию в книге Дейтел Х. Дейтел П - Как программировать на С++, нужно вывести на экран таблицу, изображение которой прикреплено. Но у меня появилось несколько вопросов: Как сделать такой же ровный вывод состояния регистров? . Пишу вывод состояния регистров так: ... http://www.cyberforum.ru/cpp-beginners/thread1232247.html
C++ Удалить (сделать прозрачными) все непрозрачные кубики, видимые хотя бы с одной из четырех сторон
Помогите, пожалуйста, отредактировать эту программу. Нужно переписать код, чтобы использовались функции. Текст задания: Поле размером mxn заполнено прозрачными и непрозрачными кубиками. Удалить (сделать прозрачными) все непрозрачные кубики, видимые хотя бы с одной из четырех сторон. (видимость анализируется до удаления какого-либо кубика). #include <windows.h>
C++ Формула, по которой можно вычислить время наступления Рагнарека
Рагнарек должен наступить с минуты на минуту. Но Один не знает, когда именно он наступит. Локи, как самый умный, сказал Одину формулу, по которой можно вычислить время наступления Рагнарека. К сожалению, Одину с одним глазом сложно уследить за всеми скобками в выражении, поэтому он решил заменить скобки первого уровня на фигурные, а второго уровня – на квадратные, остальные же оставить круглыми....
C++ При выводе минимального элемента последовательности программа выводит слишком большое число http://www.cyberforum.ru/cpp-beginners/thread1232190.html
При выводе минимального элемента программа выводит слишком большое число. #include <iostream> using namespace std; int main() { setlocale(0,""); int maximum; float numbers, amount, average, maximal_element; float minimal_element; average = 0;
C++ Sentence. Записать число прописью Once upon a time in a land far far away, inhabited only by math students, Iva and Vedran were discussing self-explanatory sentences. A part of these sentences is exactly one number and it is equal to the total number of letters in the sentence. Some examples are: “This sentence has thirtyone letters.”, “Blah blah seventeen”. Little Jurica overheard his friends' conversation and decided to... подробнее

Показать сообщение отдельно
Убежденный
Системный программист
 Аватар для Убежденный
14188 / 6203 / 984
Регистрация: 02.05.2013
Сообщений: 10,331
Завершенные тесты: 1
23.07.2014, 01:53     Оператор "delete" и ошибка "_BLOCK_TYPE_IS_VALID(pHead->nBlockUse) Error"
Цитата Сообщение от IIARTEMII Посмотреть сообщение
Что это за механизм такой, который реагирует на отсутствие виртуального деструктора, если по сути это приводит к утечке памяти, а не к программной ошибке (да, UB может привести к ошибке, а может и нет, но...)? Почему этот механизм себя проявляет только в MSVS?
Тут очень многое зависит от деталей реализации - от того, как сделаны
виртуальные таблицы в данном конкретном компиляторе и как устроен его
аллокатор памяти.

Приключения начинаются вот в этой строке:
C++
1
Base *ptr = new Der;
Если Base и Der - обычные классы, не отягощенные virtual-методами,
включая деструктор, то при касте указателя Der к Base его скалярное
значение сохранится. То есть, к примеру, если "new Der" вернет адрес
0xABCDE8, то и в ptr будет записано 0xABCDE8. В этом случае, когда
будет вызван "delete ptr", аллокатор получит все тот же адрес и
сможет корректно освободить занимаемую объектом Der память.
Хотя деструктор Der вызван не будет.

Предположим, Der унаследован не только от Base, но еще и от Megabase,
причем Megabase в списке наследования расположен раньше Base:
C++
1
class Der : public Megabase, public Base { ... };
В этом случае приведение указателя от Der к Base приведет к
изменению его скалярного значения.

Пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
 
struct Megabase
{
    virtual void somefunc() {}
};
 
struct Base
{
    virtual void anotherfunc() {}
};
 
struct Der : public Megabase, public Base {};
 
int main()
{
    using namespace std;
 
    Der  * pDer  = new Der();
    Base * pBase = pDer;
 
    cout << pDer  << endl;
    cout << pBase << endl;
 
    // delete pBase; // ???
 
    return 0;
}
> 0x9850438
> 0x985043c
Вот тут и начинаются глюки. "delete pBase" приведет к попытке
освобождения памяти по адресу 0x985043c, хотя при создании объекта
Der был возвращен адрес 0x9850438. Это равноценно тому, что в
delete передали адрес, который никогда не выделялся.
Кстати, возникновение ошибки в данном примере характерно не только
для MS Visual C++, можете проверить на любом компиляторе, который
есть под рукой.

Нечто похожее происходит и при виртуальном наследовании, так как
там "раскладка" классов в памяти заметно отличается от обычной,
хотя все это, повторюсь, очень compiler-specific:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
 
struct parent
{
    int a;
};
 
struct child : public virtual parent
{
    int b;
};
 
int main()
{
    using namespace std;
 
    child Child;
    cout << &Child.a << endl;
    cout << &Child.b << endl;
 
    return 0;
}
> 0x42f80c
> 0x42f808
Неожиданно: a размещается в памяти после b.
При обычном (невиртуальном) наследовании все было бы наоборот.

И последний пример, снова с изменением скалярного значения указателя
при касте к базовому классу:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
 
struct parent
{
    int a;
};
 
struct child : public virtual parent
{
    int b;
};
 
int main()
{
    using namespace std;
 
    child  * pChild  = new child();
    parent * pParent = pChild;
 
    cout << pChild  << endl;
    cout << pParent << endl;
 
    // delete pParent; // ???
 
    return 0;
}
> 0x5712D8
> 0x5712E0
При полиморфном удалении объекта, когда базовый класс имеет виртуальный
деструктор, аллокатор всегда получает "правильный" адрес памяти для очистки,
так что проблем, описанных выше, не возникает.
 
Текущее время: 17:36. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru