Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
3 / 3 / 0
Регистрация: 13.09.2013
Сообщений: 38
1

Динамическое размещение объекта в определённом месте памяти с последующим её освобождением

04.10.2013, 18:39. Показов 1175. Ответов 14
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени суток.

В C++ имеется возможность размещать объект по чётко определённому, указанному разработчиком, адресу в памяти. В свете этого у меня возник вопрос об освобождении памяти, использованной таким образом.

Пусть, к примеру, у меня имеется некоторый массив объектов char (выделенный ранее динамически) и указывающий на адрес, по которому вдруг потребовалось разместить объект некоторого класса A.

На вскидку, мне видится три возможных варианта освобождения памяти. В коде ниже показываю все три варианта. В каждом из них происходит вызов деструктора, но я сомневаюсь, в каждом ли из них производится освобождение памяти...

Интуитивно считаю, что в третьем варианте память должна освобождаться (деструктор там я вызываю вручную, иначе он не будет вызван). Оператору delete указываю "родной" указатель типа char, которому и была изначально выделена память.

Но вот первый и второй вариант... С одной стороны, я использовал new, а с другой - я ведь не выделял новую память, а указал адрес уже выделенной ранее... Вот что в данном случае происходит? Происходит ли освобождение памяти, или же всё ограничивается банальным вызовом деструктора без последующего освобождения памяти? Как можно определить, произошло ли освобождение памяти? Может какой инструмент для этого имеется в GCC и MSVisual Studio 2012?

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <exception>
using namespace ::std;
 
class A{
private:
    double x;
public:
    A() : x(0) { cout << "A class; ptr: " << this << " created." << endl; } 
    ~A() { cout << "A class; ptr: " << this << " destroyed." << endl; }
};
 
int main(int argc, char* argv[])
try{    
    int x = -1; // Variants of memory clearing
    while (x < 0 || x > 2) {
        cout << "Variant (0,1,2): ";
        cin >> x;
    }
    char* p = new char[sizeof(A)]; // some memory area...
    
    A* a = new(p)A(); // Place my object in the 'p' address.
    
    // Here is my basic work to do...
    
    // Now I must to free my memory:
    if(!x){ // First variant
        delete a;           
    }
    else if (x == 1){ // Second variant
        delete reinterpret_cast<A*>(p); 
    }
    else if (x == 2){ // Third variant
        a->~A();        
        delete[] p; 
    }
    else{
        throw runtime_error("Invalid variant!");
    }
    a = nullptr;
    p = nullptr;
    
    cout << endl;   
}
catch(exception& e){
    cerr << e.what() << endl;
    return 1;
}
catch(...){
    cerr << "Unknown exception." << endl;
    return 2;
}
Спасибо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.10.2013, 18:39
Ответы с готовыми решениями:

Размещение объекта в памяти
Возможно ли размещение объекта в заранее выделенной памяти, например в массиве? Тоесть не просто...

Динамическое выделение памяти для объекта класса
Скажите в чем отличие между A *ptr=new A() и A *ptr=new A;

Проблаем с освобождением памяти
Работаю в Visual Studio C++ Express написал вот такой простой код: int main(){ char *n;...

мышь в определённом месте
Здравствуйте господа програмисты!!!Как поставить курсор мыши в определённое место? Заранее всем...

14
859 / 448 / 112
Регистрация: 06.07.2013
Сообщений: 1,491
04.10.2013, 18:47 2
не понял сути вопроса...
у нас есть блок памяти char A[512];
если мы хотим использовать этот же блок под класс делаем так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Someclass
{
public:
int a;
int b;
};
 
int main(int,char**)
{
char* A = new char[512];
 
//поработали
((Someclass*)A)->a = 100;
((Someclass*)A)->b = 200;
 
//освобождаем что взяли
delete []A;
return 0;
}
0
3 / 3 / 0
Регистрация: 13.09.2013
Сообщений: 38
04.10.2013, 18:52  [ТС] 3
Цитата Сообщение от Raali Посмотреть сообщение
не понял сути вопроса...
у нас есть блок памяти char A[512];
если мы хотим использовать этот же блок под класс делаем так
Я в курсе и спрашивал о другом. В обозначенном мною варианте объект создаётся конструктором, поскольку зачастую экземпляры классов создаются именно так. Затем я показал три варианта освобождения ранее использовавшейся памяти. Вопрос был о том, насколько допустимы в использовании эти три варианта.
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
04.10.2013, 20:49 4
Рабочий только третий вариант. Остальные- неопределенное поведение, так как память, выделенная оператором new, может быть освобождена только соответствующим оператором delete.

Кстати в первом варианте проверка if (!x) лишняя. delete прекрасно работает с нулевыми указателями.
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
04.10.2013, 20:53 5
Цитата Сообщение от ct0r Посмотреть сообщение
Кстати в первом варианте проверка if (!x) лишняя. delete прекрасно работает с нулевыми указателями.
Стандартом это не гарантировано.
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
04.10.2013, 20:58 6
Цитата Сообщение от castaway Посмотреть сообщение
Стандартом это не гарантировано.
5.3.5.2
if the value of the operand of delete is the null pointer the operation
has no effect

Ну ты почитай вначале стандарт-то.
1
castaway
04.10.2013, 21:05
  #7

Не по теме:

Действительно. Не знаю почему у меня в голове это было заложено..

0
3 / 3 / 0
Регистрация: 13.09.2013
Сообщений: 38
04.10.2013, 21:12  [ТС] 8
Цитата Сообщение от ct0r Посмотреть сообщение
Кстати в первом варианте проверка if (!x) лишняя. delete прекрасно работает с нулевыми указателями.
А какое отношение нулевой указатель имеет к первому варианту?
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
04.10.2013, 21:19 9
Цитата Сообщение от include_brain Посмотреть сообщение
А какое отношение нулевой указатель имеет к первому варианту?
Точно, никакого) Но зато castaway теперь в курсе, что стандартом то гарантировано)

В общем я слишком бегло читаю код и всегда считал признаком хорошего тона числа на ноль проверять сравнением явно == 0. ! лучше проверять булевы или накрайняк указатели.
0
3 / 3 / 0
Регистрация: 13.09.2013
Сообщений: 38
04.10.2013, 21:22  [ТС] 10
Цитата Сообщение от ct0r Посмотреть сообщение
В общем я слишком бегло читаю код и всегда считал признаком хорошего тона числа на ноль проверять сравнением явно == 0.
Мне более импонирует форма, предложенная Стровструпом (которую я и использовал в коде). На вкус и цвет, все фломастеры разные.

Вопрос снят: почитал про "placement new".
0
1 / 1 / 1
Регистрация: 10.04.2013
Сообщений: 41
04.10.2013, 21:27 11
Цитата Сообщение от include_brain Посмотреть сообщение
Пусть, к примеру, у меня имеется некоторый массив объектов char (выделенный ранее динамически) и указывающий на адрес, по которому вдруг потребовалось разместить объект некоторого класса A.
А зачем так делать?
0
3 / 3 / 0
Регистрация: 13.09.2013
Сообщений: 38
04.10.2013, 21:32  [ТС] 12
Цитата Сообщение от badLogic Посмотреть сообщение
А зачем так делать?
линк.
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
04.10.2013, 21:35 13
Цитата Сообщение от include_brain Посмотреть сообщение
+ это может быть разделяемая память
+ может хочется хранить определенные объекты разных типов рядом друг с другом, чтобы избежать кэш-промахов
0
1 / 1 / 1
Регистрация: 10.04.2013
Сообщений: 41
04.10.2013, 21:44 14
Ну там же написано, что нужно удалить всего лишь оригинальный буфер.
Может сделаете доброе дело и поделитесь, что там прочитали и какой вариант истинно правильный?
0
3 / 3 / 0
Регистрация: 13.09.2013
Сообщений: 38
04.10.2013, 22:09  [ТС] 15
Цитата Сообщение от badLogic Посмотреть сообщение
какой вариант истинно правильный?
третий
0
04.10.2013, 22:09
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.10.2013, 22:09
Помогаю со студенческими работами здесь

Ошибка в функции с освобождением памяти
Здравствуйте. Столкнулся с такой ошибкой: &quot;C4700 использована неинициализированная локальная...

Удаление задачи с освобождением памяти
Привет! На стм32 стоит FriiRTOS, использует схему heap_2. Часто создаются и удаляются задачи (все...

вывод строки в определённом месте
кто знает как выводить текст в определённом месте fseek(stdout,...) не пойдёт в данном случае...

Сохранение файла в определённом месте
Здравствуйте. написал код Excel.Application exApp = new Excel.Application(); ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru