La mémoire est-tas par processus? (Ou) l'emplacement de la mémoire commune partagée par différents processus?

StackOverflow https://stackoverflow.com/questions/3147014

Question

Chaque processus peut utiliser la mémoire pour stocker des tas et de partager des données dans le processus. Nous avons une règle dans la programmation chaque fois que nous prenons un peu d'espace en mémoire tas, nous avons besoin de libérer une fois le travail est fait, sinon il conduit à des fuites de mémoire.

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

Ma question: est-mémoire tas par processus

Si OUI,

  

puis fuite de mémoire est possible que si un processus est en cours d'exécution.

Si NON,

  

cela signifie OS est capable de conserver les données dans une mémoire quelque part. Si oui, est-il un moyen d'accéder à cette mémoire par un autre processus. Aussi cela peut devenir un moyen de communication inter-processus.

Je suppose que réponse à ma question est OUI. S'il vous plaît fournir vos précieux commentaires.

Était-ce utile?

La solution

Sur presque tous les systèmes en cours d'utilisation, la mémoire tas est par processus. Sur les anciens systèmes sans mémoire protégée, la mémoire était tas système. (En un mot, c'est ce que la protection mémoire Finalité :. Il rend votre tas et pile privé à votre processus)

Dans votre exemple de code sur un système moderne, si le termine process avant delete pIntPtr est appelé, pIntPtr sera toujours libéré (bien que son destructor, pas un int a un, ne serait pas appelé.)

Notez que la mémoire protégée est un détail de mise en œuvre, pas une caractéristique du C ++ ou C normes. Un système est libre de partager la mémoire entre les processus (systèmes modernes que ne pas , car il est un bon moyen pour obtenir votre bout à bout remis à vous par un attaquant.)

Autres conseils

Dans la plupart des systèmes d'exploitation modernes chaque processus a son propre tas qui est accessible par ce processus uniquement et remis en état une fois que le processus se termine - que « privé » tas est généralement utilisé par new. De plus il pourrait y avoir un tas global (consultez Win32 GlobalAlloc() fonctions de la famille par exemple) qui est partagé entre les processus, pour l'exécution persiste du système et en effet peuvent être utilisés pour les communications interprocessus.

En général, l'allocation de mémoire à un processus qui arrive à un niveau inférieur à la gestion tas.

En d'autres termes, le tas est construit dans le processus espace d'adressage virtuel donné au processus par le système d'exploitation et est privé à ce processus. Lorsque les sorties de processus, cette mémoire est récupérée par le système d'exploitation.

Notez que C ++ ne prescrit pas cela, cela fait partie de l'environnement d'exécution dans lequel les courses de C, de sorte que les normes ISO ne dictent pas ce comportement. Ce que je veux discuter est mise en œuvre commune.

Dans UNIX, les brk et appels système de sbrk ont été utilisés pour allouer plus de mémoire du système d'exploitation pour étendre le tas. Puis, une fois le processus terminé, toute cette mémoire a été rendu à l'OS.

La façon normale pour obtenir la mémoire qui peut survivre à un processus est à mémoire partagée (sous les systèmes d'exploitation de type UNIX, pas sûr de Windows). Cette peut résultat dans une fuite, mais plus des ressources du système plutôt que les ressources du processus.

Il existe des systèmes d'exploitation à des fins spéciales qui ne sera pas la mémoire à la sortie de récupération processus. Si vous ciblez un tel système d'exploitation que vous connaissez probablement.

La plupart des systèmes ne vous permettra pas d'accéder à la mémoire d'un autre processus, mais encore une fois ... il y a des situations uniques où cela est pas vrai.

Le C ++ traite standard avec cette situation en ne faisant aucune réclamation au sujet de ce qui se passera si vous ne parvenez pas à libérer de la mémoire et la sortie, ni ce qui se passera si vous essayez de mémoire d'accès qui ne sont pas explicitement le vôtre à l'accès. Ceci est l'essence même de ce « comportement non défini » signifie et est au cœur de ce que cela signifie pour un pointeur comme « invalide ». Il y a plus de questions que simplement ces deux, mais ces deux entrent en jeu.

Normalement, le rapport O / S va récupérer toute fuite de mémoire se termine lorsque le process.

Pour cette raison, je pense qu'il est OK pour les programmeurs C pour ne jamais libérer explicitement une mémoire qui est nécessaire jusqu'à ce que le processus se termine; par exemple, des « singletons » dans un processus ne sont souvent pas explicitement libérés.

Ce comportement peut être O / S spécifique, bien que (bien qu'il soit vrai pour par exemple Windows et Linux). Théoriquement pas partie de la norme C ++

Pour des raisons pratiques, la réponse à votre question est oui. Les systèmes modernes d'exploitation libéreront généralement la mémoire allouée par un processus lorsque ce processus est arrêté. Cependant, dépendre de ce comportement est une pratique très mauvaise qualité. Même si nous pouvons être assurés que les systèmes d'exploitation toujours fonctionner de cette façon, le code est fragile. Si une fonction qui ne parvient pas à libérer de la mémoire devient soudainement réutilisé dans un autre but, il pourrait se traduire par une fuite de mémoire au niveau de l'application.

Cependant, la nature de cette question et l'exemple affiché exige, sur le plan éthique, pour moi de signaler que vous et votre équipe à regarder RAII.

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

Ce code relents de fuites de mémoire. Si quoi que ce soit dans [...] lancers francs, vous avez une fuite de mémoire. Il existe plusieurs solutions:

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

Deuxième solution à l'aide nothrow (pas nécessairement beaucoup mieux que la première, mais permet l'initialisation sensible pIntPtr au moment où elle est définie):

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

Et la manière simple:

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

Dans ce dernier et le plus bel exemple, il n'y a pas besoin de faire appel de suppression sur pIntPtr comme cela se fait automatiquement quelle que soit la façon dont nous quitter ce bloc (hourra pour RAII et pointeurs intelligents).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top