Всем привет.
Такое вот дело, я не могу найти нигде информацию о том, как поступает компилятор с++ по стандарту, когда выделяется память через new. В общем, если в паскале например создать объект внутри функции и передать указатель на этот объект внешнему коду, то теоритически в любой момент данный объект может быть затёрт, потому так желательно не делать.
Но вопрос в том, как поступает c++ в таких ситуациях, если я выделяю память через new? Понятное дело, что все локальные переменные будут недоступны из вне (об этом не писать :) не нуб) , а вот сама память, останется выделена, и будет доступна, пока я сам её не освобожу, или же будет освобождена (не затёрта, а именно освобождена) в момент выхода из функции?
Заранее всем спасибо. Просто начал учить с++, хочу написать что-то толковое, а не могу основ поведения компилятора найти )))
Другие языки программирования и технологии
будет ли очищена память вне функции (с++)
Память выделяется по указателю и не C++, а процессом, согласно распределителя памяти. Далее операционная система выделяет память процессу страницами (в Windows по 4 KB), а процесс распределяет его по своему усмотрению, до тех пор пока память не закончится, потом он опять просит систему выделить ему очередную страницу памяти. Адреса указателей по которым динамически выделяется память хранятся в статической памяти. Так система в состоянии контролировать выделенную по указателю память. До тех пор пока процесс не потеряет указатель, он может удалить по нему выделенную память. Система контролирует только сам указатель. Если он стал NULL, а память не освобождена, то процесс и система теряет контроль над данными. Однако сами данные сохраняются в ячейках памяти и для системы они будут заняты. Так как очистку инициирует процесс, а не система. Это называется утечкой памяти.
Говорить о выделении памяти как о чём-то само-собой разумеющимся не приходится. Правильнее будет сказать, что процесс предпринимает попытку выделить память под данные. Которая, вполне, может закончится неудачей. Программист должен предусматривать такой исход.
Память следует освобождать после того как хранимые в ней данные станут больше не нужны. Освобождать память следует в той же функции, где под неё была выделена память, то есть создан указатель. Например:
#include <iostream>
using namespace std;
// предпринимаем попытку выделения памяти под целочисленный массив
int * mymemset(const size_t size_arr) { return new (nothrow) int [size_arr]; }
bool memdestroy(int * ptr_arr) {
if (ptr_arr) { // если указатель на массив существует
delete[] ptr_arr; // память освобождаем
return true; // сообщаем об успехе
}
return false; // иначе о неудачной попытке освобождения памяти
}
int main() {
// создаём указатель и выделиляем по нему память под массив из двух элементов
int * v = mymemset(2); // указатель здесь и память освобождаем здесь! !
// заполняем его данными
v[0] = 25;
v[1] = 42;
// выводим данные на консоль
cout << v[0] << endl << v[1] << endl;
// предпринимаем попытку освобождения памяти по указателю на массив
if (memdestroy(v)) { // указатель здесь и память освобождаем здесь! !
cout << "Good!"; // если функция вернёт
// обнуляем указатель, чтобы избежать повторного обращения к нему и попытки повторного освобождения памяти
v = NULL;
} else cout << "Error!"; // если указатель = NULL, то следует проверить код на ошибки
cout << endl;
cin.get();
return 0;
}
P.S. Что же касаемо компилятора, то ему глубоко насрать на то, освобождите вы память или нет.
Говорить о выделении памяти как о чём-то само-собой разумеющимся не приходится. Правильнее будет сказать, что процесс предпринимает попытку выделить память под данные. Которая, вполне, может закончится неудачей. Программист должен предусматривать такой исход.
Память следует освобождать после того как хранимые в ней данные станут больше не нужны. Освобождать память следует в той же функции, где под неё была выделена память, то есть создан указатель. Например:
#include <iostream>
using namespace std;
// предпринимаем попытку выделения памяти под целочисленный массив
int * mymemset(const size_t size_arr) { return new (nothrow) int [size_arr]; }
bool memdestroy(int * ptr_arr) {
if (ptr_arr) { // если указатель на массив существует
delete[] ptr_arr; // память освобождаем
return true; // сообщаем об успехе
}
return false; // иначе о неудачной попытке освобождения памяти
}
int main() {
// создаём указатель и выделиляем по нему память под массив из двух элементов
int * v = mymemset(2); // указатель здесь и память освобождаем здесь! !
// заполняем его данными
v[0] = 25;
v[1] = 42;
// выводим данные на консоль
cout << v[0] << endl << v[1] << endl;
// предпринимаем попытку освобождения памяти по указателю на массив
if (memdestroy(v)) { // указатель здесь и память освобождаем здесь! !
cout << "Good!"; // если функция вернёт
// обнуляем указатель, чтобы избежать повторного обращения к нему и попытки повторного освобождения памяти
v = NULL;
} else cout << "Error!"; // если указатель = NULL, то следует проверить код на ошибки
cout << endl;
cin.get();
return 0;
}
P.S. Что же касаемо компилятора, то ему глубоко насрать на то, освобождите вы память или нет.
Насчет паскаля тоже бред написан.
Динамическая память, как и в С, выделяется в куче и не будет освобождена до тех пор, пока это не будет сделано явно, через Dispose/FreeMem или вызовом деструктора объекта. Написанное верно только для статических объектов, но кто ж в здарвом уме их использует таким образом?
Динамическая память, как и в С, выделяется в куче и не будет освобождена до тех пор, пока это не будет сделано явно, через Dispose/FreeMem или вызовом деструктора объекта. Написанное верно только для статических объектов, но кто ж в здарвом уме их использует таким образом?
в C++ память не будет освобождена, пока этого не сделать явно.
в perl - память будет освобождена при выходе из контекста,
в java и c# - через некоторое время сборщиком мусора (запустите minecraft и обратите внимание на динамику использования памяти. очень забавно)
все это при условии, что на объект не осталось ни одной ссылки
в managed С++ есть gcnew для таких целей.
в чистом C++ все делается руками (хотя и автоматическое управление памятью тоже возможно например с помощью auto_ptr/unique_ptr)
можно смело делать
А *myfunc() {
return new A();
}
...
A *b = myfunc();
память не распределится.
в perl - память будет освобождена при выходе из контекста,
в java и c# - через некоторое время сборщиком мусора (запустите minecraft и обратите внимание на динамику использования памяти. очень забавно)
все это при условии, что на объект не осталось ни одной ссылки
в managed С++ есть gcnew для таких целей.
в чистом C++ все делается руками (хотя и автоматическое управление памятью тоже возможно например с помощью auto_ptr/unique_ptr)
можно смело делать
А *myfunc() {
return new A();
}
...
A *b = myfunc();
память не распределится.
Похожие вопросы
- Как очистить память ?
- Как полностью очистить память на компьютере? Желательно пошагово.
- Напишите пожалуйста примеры функций выделения памяти и освобождения памяти (с аргументами) в С++ ?
- Вопрос для тех кто знает точный ответ, язык C про функции все подробности вопроса внутри...
- Turbo Pascal. 2 задачи на процедуры и функции
- Вопрос про возвращаемое значение из функции в С++.
- Помогите з функциями в с++ плиииз
- Функции в языке программирования C.
- PASCAL. В чем отличие процедур от функций. И любую ли задачу можно решить с помощью функции?
- Функции в Си