Куча памяти на процесс?(или) Общая область памяти, используемая разными процессами? - PullRequest
9 голосов
/ 30 июня 2010

Каждый процесс может использовать память кучи для хранения и обмена данными внутри процесса. У нас есть правило в программировании всякий раз, когда мы занимаем некоторое пространство в куче памяти, мы должны освободить его после выполнения задания, иначе это приведет к утечкам памяти.

int *pIntPtr = new int;
.
.
.
delete pIntPtr;

Мой вопрос: есть ли куча памяти для каждого процесса?

Если ДА,

тогда утечка памяти возможна только тогда, когда процесс находится в рабочем состоянии.

Если НЕТ,

тогда это означает, что ОС может где-то хранить данные в памяти. Если так, есть ли способ получить доступ к этой памяти другим процессом. Также это может стать способом межпроцессного взаимодействия.

Полагаю, ответ на мой вопрос - ДА. Пожалуйста, оставьте ценный отзыв.

Ответы [ 6 ]

16 голосов
/ 30 июня 2010

Почти на каждой системе, используемой в настоящее время, куча памяти зависит от процесса. В старых системах без защищенной памяти куча была общесистемной. (Короче говоря, вот что защищенная память делает : она делает вашу кучу и стек частной для вашего процесса.)

Таким образом, в вашем примере кода в любой современной системе, если процесс завершится до вызова delete pIntPtr, pIntPtr все равно будет освобожден (хотя его деструктор, а не int, не имеет такового).

Обратите внимание, что защищенная память - это деталь реализации, не - особенность стандартов C ++ или C. Система свободна в распределении памяти между процессами (современные системы просто не , потому что это хороший способ получить задницу от злоумышленника.)

3 голосов
/ 30 июня 2010

В большинстве современных операционных систем каждый процесс имеет свою собственную кучу, доступную только этому процессу и возвращаемую после завершения процесса - эта «частная» куча обычно используется new.Также может существовать глобальная куча (см., Например, функции семейства Win32 GlobalAlloc()), которая распределяется между процессами, сохраняется во время работы системы и действительно может использоваться для межпроцессного взаимодействия.

2 голосов
/ 30 июня 2010

Обычно выделение памяти процессу происходит на более низком уровне, чем управление кучей.

Другими словами, куча строится в виртуальном адресном пространстве процесса, предоставленном процессу операционной системой, и являетсяличное для этого процесса.Когда процесс завершается, эта память освобождается операционной системой.

Обратите внимание, что C ++ не требует этого, это является частью среды выполнения, в которой работает C ++, поэтому стандарты ISO не диктуют такое поведение.Я обсуждаю общую реализацию.

В UNIX системные вызовы brk и sbrk использовались, чтобы выделить больше памяти из операционной системы для расширения кучи.Затем, когда процесс завершился, вся эта память была возвращена ОС.

Нормальный способ получить память, которая может пережить процесс, - это использовать совместно используемую память (в операционных системах типа UNIX, не уверен в Windows).Это может привести к утечке, но больше системных ресурсов, чем ресурсов процесса.

1 голос
/ 30 июня 2010

Существуют специальные операционные системы, которые не возвращают память при выходе из процесса. Если вы нацелены на такую ​​ОС, вы, вероятно, знаете.

Большинство систем не позволяют вам получить доступ к памяти другого процесса, но опять же ... есть некоторые уникальные ситуации, когда это не так.

Стандарт C ++ имеет дело с этой ситуацией, не делая никаких заявлений о том, что произойдет, если вам не удастся освободить память и затем завершить работу, а также о том, что произойдет, если вы попытаетесь получить доступ к памяти, которая явно не принадлежит вам. Это сама суть того, что означает «неопределенное поведение», и суть того, что означает «недействительный» указатель. Есть больше проблем, чем только эти два, но эти два играют свою роль.

0 голосов
/ 30 июня 2010

Для практических целей ответ на ваш вопрос - да.Современные операционные системы обычно освобождают память, выделенную процессом, когда этот процесс выключен.Однако зависеть от этого поведения - очень плохая практика.Даже если мы можем быть уверены, что операционные системы всегда будут работать таким образом, код хрупок.Если какая-то функция, которая не освобождает память, внезапно повторно используется для другой цели, это может привести к утечке памяти на уровне приложения.

Тем не менее, характер этого вопроса и приведенный пример требует, с этической точки зрения, от меняукажите вам и вашей команде на RAII.

int *pIntPtr = new int;
...
delete pIntPtr;

Этот код пахнет утечками памяти.Если что-то [...] выбрасывает, у вас есть утечка памяти.Существует несколько решений:

int *pIntPtr = 0;
try
{
    pIntPtr = new int;
    ...
}
catch (...)
{
    delete pIntPtr;
    throw;
}
delete pIntPtr;

Второе решение с использованием nothrow (не обязательно намного лучше, чем первое, но допускает разумную инициализацию pIntPtr во время его определения):

int *pIntPtr = new(nothrow) int;
if (pIntPtr)
{
    try
    {
         ...
    }
    catch (...)
    {
        delete pIntPtr;
        throw;
    }
    delete pIntPtr;
}

Исамый простой способ:

scoped_ptr<int> pIntPtr(new int);
...

В этом последнем и лучшем примере нет необходимости вызывать delete для pIntPtr, поскольку это делается автоматически независимо от того, как мы покидаем этот блок (ура для RAII и интеллектуальных указателей).

0 голосов
/ 30 июня 2010

Обычно O / S восстанавливает любую утечку памяти, когда процесс завершается.

По этой причине я считаю, что для программистов на C ++ нормально никогда не освобождать явно какую-либо память, которая требуется до завершения процесса; например, любые «синглеты» внутри процесса часто не освобождаются явно.

Это поведение может быть специфичным для O / S (хотя это верно, например, для Windows и Linux): теоретически не является частью стандарта C ++.

...