Propriétés d'un pointeur sur un tableau de longueur nulle

21

Considérer

int main()
{
    auto a = new int[0];
    delete[] a; // So there's no memory leak
}

Entre l'initialisation et la suppression de la copie, êtes-vous autorisé à lire le pointeur sur a + 1?

En outre, la langue ne permet au compilateur de jeu aà nullptr?

Bathsheba
la source
2
@Fareanor: Vous pouvez lire aà coup sûr (vous ne pouvez certainement pas le déréférencer).
Bathsheba
8
@RasmiRanjanNayak: C'est du hogwash.
Bathsheba
2
@RasmiRanjanNayak Oh mon ... non
Ted Lyngmo
1
@TedLyngmo: Quand je dis "lisez le pointeur sur a + 1", le code suivant est-il auto b = a + 1;un comportement non défini? (Je pense que c'est).
Bathsheba
2
@Ayxan Je suppose que dans le cas où 0est en fait le résultat d'une expression que vous ne saurez pas avant l'exécution. Puisqu'il new int[0]est sûr, il pourrait vous éviter de vous soucier de certains cas de branchement / spéciaux. Imaginez si je devais initialiser un std::vectoravec std::vector<int> v(0);.
scohe001

Réponses:

3
    auto a = new int[0];

Selon [basic.compound.3] , la valeur stockée dans adoit être l'une des suivantes:

  1. Un pointeur sur un objet (de type int)
  2. Un pointeur après la fin d'un objet
  3. Nul
  4. Invalide

Nous pouvons exclure la première possibilité car aucun objet de type n'a été intconstruit. La troisième possibilité est exclue car C ++ nécessite le retour d'un pointeur non nul (voir [basic.stc.dynamic.allocation.2] ). Il nous reste donc deux possibilités: un pointeur après la fin d'un objet ou un pointeur invalide.

Je serais enclin à voir acomme un pointeur passé la fin, mais je n'ai pas de référence fiable pour établir définitivement cela. (Il y a, cependant, une forte implication de ceci dans [basic.stc] , voir comment vous pouvez deletece pointeur.) Je vais donc envisager les deux possibilités dans cette réponse.

Entre l'initialisation et la suppression de la copie, êtes-vous autorisé à lire le pointeur sur a + 1?

Le comportement n'est pas défini, comme dicté par [expr.add.4] , quelle que soit la possibilité ci-dessus qui s'applique.

Si aest un pointeur passé la fin, alors il est considéré comme pointant vers l'élément hypothétique à l'index 0d'un tableau sans éléments. L'ajout de l'entier jà an'est défini que lorsque 0≤0+j≤n, où nest la taille du tableau. Dans notre cas, nest nul, donc la somme a+jn'est définie que lorsque jest 0. En particulier, l'ajout 1n'est pas défini.

Si aest invalide, alors nous tombons proprement dans "Sinon, le comportement n'est pas défini". (Sans surprise, les cas définis ne couvrent que des valeurs de pointeur valides.)

En outre, la langue ne permet au compilateur de jeu aà nullptr?

Non. D'après la [basic.stc.dynamic.allocation.2] mentionnée ci-dessus : "Si la demande aboutit, la valeur renvoyée par une fonction d'allocation remplaçable est une valeur de pointeur non nulle" . Il existe également une note de bas de page indiquant que C ++ (mais pas C) nécessite un pointeur non nul en réponse à une demande nulle.

JaMiT
la source
1
S'il s'agissait d'une valeur de pointeur non valide, vous aurez de sérieux problèmes avec eel.is/c++draft/basic.stc#4
TC
@TC Vrai, cela implique fortement qu'il ne peut pas s'agir d'une valeur de pointeur non valide.
JaMiT
23

Selon une récente discussion sur le réflecteur CWG à la suite du numéro éditorial 3178 , new int[0]produit ce qui est actuellement appelé une valeur de pointeur "après la fin" .

Il s'ensuit que acela ne peut pas être nul et a + 1n'est pas défini par [expr.add] / 4 .

TC
la source
4
"Selon une récente discussion du réflecteur CWG à la suite du numéro éditorial 3178, new int[0]produit ce qui est actuellement appelé une valeur de pointeur" après la fin "" Ce n'est pas exact. Il n'y a pas eu beaucoup de discussions. Une personne a suggéré que la valeur soit "pointeur au-delà de la fin d'un objet", et cette déclaration a été remise en question car dans le cas d'un tableau avec des 0éléments, il n'y a aucun objet devant être passé la fin de.
Language Lawyer
@LanguageLawyer il ne fait aucun doute que ce a + 1n'est pas défini dans tous les cas, donc votre point ne concerne que si apeut être nul?
MM
Il ne semble pas y avoir de désaccord sur la sémantique prévue, ni que le nom actuel de cette catégorie de valeurs de pointeur ne convient pas à ce scénario.
TC
@MM Je pense que ce a + 1n'est pas défini et peut-être que la valeur résultante du pointeur sera appelée "pointeur après la fin". Je ne dis pas que la réponse est fausse. Il est légèrement inexact, car on pourrait comprendre qu'il y a eu une longue discussion avec un consensus selon lequel il suffit de spécifier que le résultat est "pointeur après la fin" est suffisant pour résoudre le problème. Le problème avec "pointeur au-delà de la fin" est qu'il est au-delà de la fin d'un objet et soustraire 1d'une telle valeur de pointeur donne un pointeur à l'objet, ce qui ne devrait probablement pas être le cas pour les tableaux d' 0éléments.
Avocat en langues
2
@Bathsheba Pensez-vous qu'il pourrait y avoir quelque chose de plus faisant autorité au sujet d'un libellé défectueux?
Law Lawyer