Pourquoi ne pouvons-nous pas créer des objets trivialement constructibles en utilisant malloc si le constructeur trivial par défaut n'effectue aucune action?

14

J'ai du mal à comprendre le paragraphe suivant cité dans cppreference sur le constructeur par défaut trivial. J'ai recherché stackoverflow mais je n'ai toujours pas obtenu de réponse claire. Alors s'il vous plaît, aidez-moi.

Un constructeur par défaut trivial est un constructeur qui n'effectue aucune action. Tous les types de données compatibles avec le langage C (types POD) sont trivialement constructibles par défaut. Contrairement à C, cependant, les objets avec des constructeurs par défaut triviaux ne peuvent pas être créés en réinterprétant simplement le stockage correctement aligné, comme la mémoire allouée avec std :: malloc: placement-new est requis pour introduire formellement un nouvel objet et éviter un comportement potentiellement indéfini.

Plus précisément, si le constructeur par défaut trivial ne fait rien, pourquoi ne pouvons-nous pas réinterpréter le stockage et prétendre qu'il existe un objet avec le type donné? Pourriez-vous s'il vous plaît fournir quelques exemples pour le comportement non défini potentiel que cela pourrait provoquer?

Liu Sha
la source
Le travail le plus important d'un compilateur n'est pas de compiler le code source mais de rejeter le code éventuellement invalide. Il ne peut pas faire cela lorsque vous utilisez malloc ().
Hans Passant
6
Les raisons sont très simples. Moins il y a d'opportunités pour le programmeur de faire des choses folles, plus il y a d'opportunités pour le compilateur de faire des choses folles (optimisations agressives).
n. «pronoms» m.
1
Pour des raisons similaires que vous ne pouvez pas simplement *reinterpret_cast<float*>(&someNonFloatObject) = 0.1f;. C ++ a un concept d'objets et de durées de vie d'objet, spécifié sur la machine abstraite, et ce n'est pas parce qu'il n'y a pas d'instructions CPU pour créer un objet à partir du stockage qu'il n'y a pas de différence sur la machine abstraite.
Max Langhof
1
@HansPassant Un compilateur qui rejette tout le code rejette tout le code non valide. Quoi qu'il en soit, ce n'est pas le travail du copilateur de rejeter les programmes qui ont UB.
n. «pronoms» m.
1
stackoverflow.com/q/52154744
StoryTeller - Unslander Monica

Réponses:

7

P0593R5 donne cet exemple:

struct X { int a, b; };
X *make_x() {
  X *p = (X*)malloc(sizeof(struct X));
  p->a = 1;
  p->b = 2;
  return p;
}

et explique:

Lorsqu'il est compilé avec un compilateur C ++, ce code a un comportement indéfini, car p-> a tente d'écrire dans un sous-objet int d'un objet X, et ce programme n'a jamais créé ni un objet X ni un sous-objet int.

Par [intro.object] p1,

Un objet est créé par une définition, par une nouvelle expression, lors du changement implicite du membre actif d'une union, ou lorsqu'un objet temporaire est créé.

... et ce programme n'a fait aucune de ces choses.

En pratique, cela fonctionne et la situation UB est davantage considérée comme un défaut de la norme qu'autre chose. L'objectif global du document est de proposer un moyen de résoudre ce problème et des cas similaires sans casser d'autres choses.

AProgrammer
la source
1

Pour des raisons de "pureté".

L'alternative et le statu quo actuel étaient que chaque région de stockage contiendrait tous les objets convenant à ce stockage, en même temps. Certains membres du comité sont inquiets du statu quo et beaucoup de gens craignent la notion d'avoir une infinité d'objets au même endroit (dans un état virtuel non initialisé).

Personne n'a jamais été en mesure de montrer un problème logique avec la présence infinie d'objets dans une région de stockage.

Parce qu'ils avaient différentes sections de la norme disant des choses contradictoires, les membres du comité ont simplement décidé de prendre au sérieux l'une des pires parties de la norme.

En outre, l'utilisation de littéraux de chaîne n'est strictement pas autorisée, si vous prenez vraiment au sérieux cette partie de la norme.

curiousguy
la source
l'utilisation de littéraux de chaîne n'est strictement pas autorisée . Il existe un problème CWG similaire à propos des type_infoobjets. Avez-vous signalé des littéraux de chaîne?
Avocat