6
votes

Y a-t-il un danger pour appeler gratuitement () ou Supprimer au lieu de supprimer []?


3 commentaires

Je ne crois pas que ce soit un duplicata, je pose des questions différentes très spécifiques et je n'ai aucun intérêt pour les connotations de montage


Non, c'est un duplicata. Vous demandez à la exacte la même question », ai-je autorisé à remplacer Supprimer pour Suppr []". Et la réponse est la même que dans tous les threads précédents où la même chose a été posée: "Non, vous n'êtes pas. C'est un comportement indéfini".


Si vous voulez demander à Autres questions Comment supprimer [] savoir combien d'objets à supprimer », puis créez une nouvelle question pour cela, donnez-lui son propre titre. Pour que d'autres personnes qui veulent Demander la même chose sera capable de le trouver.


10 Réponses :


1
votes

Pour les types primitifs, tels que CHAR, INT, y a-t-il une différence entre:

Je dirais que vous obtiendrez un comportement indéfini. Donc, vous ne devriez pas compter sur un comportement stable. Vous devez toujours utiliser de nouvelles / supprimées, neufs [] / Suppr [] et Malloc / Gratuit paires.


3 commentaires

Non, M "Mise en œuvre définie" est le terme utilisé par l'ISO lorsqu'un fournisseur de compilateur doit documenter leur choix. Il n'y a pas de telle obligation dans ce cas. Nasal Lesamons sont autorisés sans avertissement.


Il a déjà été discuté ici: Stackoverflow.com/Questtions/1553382/...


Je ne savais pas que ce terme utilisé par l'ISO. Fixé.



1
votes

C'est un comportement indéfini. Par conséquent, l'anser est: Oui, il pourrait y avoir un danger. Et il est impossible de prédire exactement ce qui va déclencher des problèmes. Même si cela fonctionne une fois, cela fonctionnera-t-il à nouveau? Cela dépend-il du type? Compte d'élément?


0 commentaires

16
votes

Ce comportement indéfini (le plus probablement va corrompre le tas ou le programme immédiatement) et vous ne devriez jamais le faire. Seule la mémoire libre avec une primitive correspondant à celle utilisée pour allouer cette mémoire.

violation de cette règle peut conduire à un fonctionnement correct par coïncidence, mais le programme peut casser une fois que tout est modifié - le compilateur, l'exécution, les paramètres du compilateur. Vous ne devriez jamais s'appuyer sur un tel fonctionnement approprié et vous y attendez.

Suppr [] utilise des données de service spécifiques au compilateur pour déterminer le nombre d'éléments. Habituellement, un bloc plus gros est attribué lorsque Nouveau [] est appelé, le numéro est stocké au début et l'appelant est donné l'adresse derrière le numéro stocké. Quoi qu'il en soit, Suppr [] s'appuie sur le bloc étant attribué par Nouveau [] , pas rien d'autre. Si vous associez quelque chose, sauf Nouveau [] avec Suppr [] ou vice versa que vous rencontrez un comportement non défini.


0 commentaires

10
votes

Lire la FAQ: 16.3 puis-je libérer () Les pointeurs alloués à nouveau? Puis-je supprimer des pointeurs alloués avec malloc ()?

est-il important dans le cas ci-dessus, voir que tous les éléments de S sont alloués contiguës, et il ne devrait pas être possible de supprimer une partie de la matrice?

Oui, c'est.

Comment supprimer [] déduire le nombre d'objets au-delà du premier, cela ne signifie-t-il pas qu'il doit connaître la taille de la région de mémoire allouée?

Le compilateur doit savoir. Voir FAQ 16.11

Parce que le compilateur stocke cette information.

Ce que je veux dire, c'est que le compilateur nécessite différents Supprimer S pour générer un code de conservation approprié. J'espère que cela est clair maintenant.


7 commentaires

Si le compilateur stocke des informations requises pour Suppr [], pourquoi ne peut-il pas être suffisamment intelligente pour fonctionner avec une suppression simple?


"Parce que le compilateur stocke cette information." C'est une charge de non-sens. L'opérateur ne conserve-t-il que les doublons de toutes les allocations avec le nombre d'éléments pour les allocations de réseau? Non, cela semble improbable et très inefficace pour moi.


@Anacrolix: Je me réfère à des informations sur le comptage de livres que le compilateur gère pour les allocations / offlocations. Je ne suis pas sûr de ce que vous entendez par des doublons. Vs utilisé pour conserver le nombre d'éléments de tableau juste avant le début de la matrice. Pouvez-vous fournir des implémentations alternatives?


@Vanja: Pour une simple nouvelle / supprime, des informations beaucoup moins de comptabilité sont nécessaires. Pour les tableaux, d'autre part, le compilateur doit allouer un peu plus que ce que vous utiliserez.


@Vanja: Si vous souhaitez utiliser la vanille Supprimer pour un seul objet et un pointeur à un tableau d'objets, le compilateur ne le saurait pas de l'autre. FAQ 16.11


Ce n'est pas le compilateur qui stocke cette information, c'est le temps d'exécution. Veuillez mettre à jour votre réponse, la différence est importante. Le compilateur ne peut pas stocker ces informations car il n'est pas connu au moment de la compilation.


@Dircrange: en fait, puisque vous pouvez remplacer les opérateurs de nouveaux / Supprimer, vous pouvez stocker les informations comme vous qui. Effectivement, la plupart des implémentations stockent la taille de la matrice juste avant le premier élément afin que vous puissiez généralement le trouver avec un petit décalage (négatif).



4
votes

oui, c'est dangereux!

ne le faites pas!

Cela conduira à des accidents de programmation ou un comportement même pire!

pour les objets alloués avec nouveau vous doit utiliser Supprimer ;

pour les objets alloués avec Nouveau [] vous doit Utiliser Suppr [] ; ;

pour les objets alloués avec masloc () ou calloc () vous doit utiliser gratuit () ; / p>

Sachez également que pour tous ces cas, il est illégal de supprimer / libérer un pointeur déjà supprimé / libéré une seconde fois. Gratuit peut également être appelé avec NULL. Calling Supprimer / Supprimer [] avec NULL est légal.


3 commentaires

C'est bien connu. Je demande des cas spécifiques.


"" GRATUIT () libère l'espace mémoire pointé par PTR, qui a dû être renvoyé par un appel précédent à Malloc (), CalloC () ou Realloc (). Sinon, ou si libre (PTR) a déjà été appelé auparavant, un comportement indéfini se produit. Si PTR est NULL, aucune opération n'est effectuée. "" ". Notez la clause sur NULLL. De Linux.die.net/man/3/free , mais je n'ai pas de spécification C formelle C pratique.


Il n'y a pas de cas spécifique. Ce n'est pas permis.



3
votes

Oui, il y a un vrai danger pratique. Même les détails de la mise en œuvre, rappelez-vous que opérateur Nouveau / opérateur Supprimer et Opérateur Nouveau [] / Opérateur Supprimer [] Les fonctions peuvent être remplacées complètement indépendamment. Pour cette raison, il est sage de penser à nouveau / suppression , nouveau [] / supprimer [] , malloc / libre etc.) , des méthodes complètement indépendantes d'allocaton de mémoire, qui n'ont absolument rien en commun.


2 commentaires

Même s'ils peuvent être remplacés de manière indépendante, il est généralement conseillé de les remplacer tous (comprenant le placement nouveau) ou aucun du tout.


Oui peut-être. Mais même s'ils sont tous remplacés, ils peuvent toujours allouer de la mémoire de différents pools de mémoire avec différents principes de gestion de la mémoire (pour des raisons évidentes, comme les tailles de blocs dans les fonctions «[]» sont variable, même pour le même type d'objet, tout en restant [] 'Fonctions qu'ils ne sont pas), faisant ainsi une utilisation croisée complètement infaisable.



0
votes

Bien que cela puisse sembler de manière logique que vous puissiez mélanger de nouvelles [] et libres ou de suppression au lieu de supprimer [], cela se situe sous l'hypothèse sur le compilateur étant assez simpliste, c'est-à-dire que cela utilisera toujours MALLOC ( ) Pour mettre en œuvre l'allocation de mémoire pour les nouveaux [].

Le problème est que si votre compilateur dispose d'un optimiseur suffisamment intelligent, cela pourrait voir qu'il n'y a pas de "Supprimer []" correspondant au nouveau [] pour l'objet que vous avez créé. Il pourrait donc supposer que cela peut récupérer la mémoire de n'importe où, y compris la pile afin de sauvegarder le coût d'appel du véritable malloc () pour le nouveau []. Ensuite, lorsque vous essayez d'appeler gratuitement () ou du mauvais type de Supprimer, il est susceptible de dysfonctionnement difficile.


0 commentaires

2
votes

Supprimer réalise les éléments au-delà du premier dans un tableau?

Non. Supprimer ne distribuera que le premier élément quel que soit le compilateur que vous faites cela. Cela peut travailler dans certains cas, mais c'est co-accessoire.

est-il important dans le cas ci-dessus, voir que tous les éléments de s sont alloués contiguë, et il ne devrait pas être possible de supprimer une partie de la matrice?

dépend de la façon dont la mémoire est marke aussi libre. Encore une fois la mise en œuvre dépendante.

Pour des types plus complexes, supprimerait appeler le destructeur d'objets au-delà du premier?

Non. Essayez ceci: xxx

Comment supprimer [] déduire le nombre de Objets au-delà du premier, ne serait pas cela signifie qu'il doit connaître la taille de la Région de mémoire allouée?

Oui, la taille est stockée un endroit. Où il est stocké dépend de la mise en œuvre. Exemple, l'allocateur pourrait stocker la taille dans un en-tête précédant l'adresse allouée.

Et si la région de la mémoire était alloué avec un surplomb pour raisons de performance? Par exemple un pourrait supposer que tous les allocateurs ne sont pas tous fournirait une granularité d'un octet unique. Alors n'importe quel particulier L'allocation pourrait dépasser le nécessaire taille pour chaque élément par un tout élément ou plus.

C'est pour cette raison que l'adresse renvoyée est faite pour aligner les limites des mots. Le "surplomb" peut être vu à l'aide de la taille de l'opérateur et s'applique également aux objets sur la pile.

Pour les types primitifs, tels que CHAR, INT, y a-t-il une différence entre ...?

Oui. MALLOC et Nouveau pourraient utiliser des blocs de mémoire séparés. Même si ce n'était pas le cas, c'est une bonne pratique de ne pas supposer qu'ils sont les mêmes.


3 commentaires

Je pense que vous voulez dire que New et Malloc pourrait utiliser différents allocateurs?


Il peut y avoir du "surhang" supplémentaire. L'alignement a à voir avec l'adresse de départ du bloc. Il est possible que pour des raisons de performance, un allocator utilise plus de mémoire. Par exemple, il existe des allocateurs qui n'allocient que des blocs avec des tailles qui sont une puissance de 2. Si vous demandez 33 octets, vous obtenez un bloc de taille 64. Cela facilite la gestion de la liste des blocs alloués et gratuits beaucoup plus facilement / plus rapides, à la dépense d'utilisation accrue de la mémoire. Il peut même être possible que l'allocateur connaisse la taille de l'allocation de juste l'adresse de départ, nier la nécessité de stocker des informations supplémentaires.


@Anacrolix: Vous pouvez être juste bien que l'allocator est généralement le système d'exploitation. Ma réponse repose principalement sur l'exemple d'allocator en K & R ... Je suppose que chaque allocator obtient une partie différente de la mémoire du système d'exploitation.



2
votes

Raymond Chen (Microsoft Developer) dispose d'un article en profondeur couvrant Scaler vs. Seletes vectoriels, et donne des antécédents aux différences. Voir:

http://blogs.msdn.com/oldnewthing /Rarchive/2004/02/03/66660.aspx


0 commentaires

0
votes

Étape 1 Lisez ceci: What-Is-the-différence - entre-neuf-Suppren-and-Malloc-Free

Vous regardez uniquement ce que vous voyez du côté du développeur.
Ce que vous n'envisageez pas, c'est comment la LIB STD Gestion de la mémoire. P>

La première différence est que le nouveau et Malloc allouent MEMROY de deux zones différentes en mémoire (Nouveauté de Freestore et Malloc de Heap (Ne vous concentrez pas. Sur les noms, ils sont essentiellement des tas, ceux-ci sont juste là des noms officiels de la norme)). Si vous allouez d'un et de désaffecter à l'autre, vous gênerez les structures de données utilisées pour gérer la mémoire (il n'y a pas de gurantie, ils utiliseront la même structure pour la gestion de la mémoire). P>

Quand vous allouez Un bloc comme celui-ci: p>

Memory   Value      Comment
0x08     0x40       // Chunk Size  
0x16     0x10000008 // Free list for Chunk size 40
0x24     0x08       // Block Size
0x32     ??         // Address returned by New.
0x40     0x08       // Pointer back to head block.
0x48     0x0x32     // Link to next item in a chain of somthing.


0 commentaires