web-dev-qa-db-fra.com

Obtention d'un pointeur suspendu en renvoyant un pointeur à partir d'un tableau local de style C

Je suis un peu confus par le code suivant:

#include <iostream>

const char* f()
{
    const char* arr[]={"test"};
    return arr[0];
}

int main()
{
    auto x = f();
    std::cout << x;
}

À mon avis, ce code devrait être UB (comportement non défini). Nous renvoyons un pointeur sur un élément de tableau de style C à l'intérieur d'une portée locale. Les choses devraient mal tourner. Cependant, aucun des compilateurs avec lesquels j'ai testé ne s'est plaint (j'ai utilisé -Wall -Wextra -pedantic sur g ++ et clang). valgrind ne se plaint pas non plus.

Le code ci-dessus est-il valide ou est-il UB comme on pourrait le penser?

PS: en cours d'exécution, il semble produire le résultat "correct", c'est-à-dire afficher "test", mais ce n'est pas une indication d'exactitude.

48
vsoftco

Non, ce n'est pas UB.

Cette:

const char* f()
{
    const char* arr[]={"test"};
    return arr[0];
}

Peut être réécrit en équivalent:

const char* f()
{
    const char* arr0 = "test";
    return arr0;
}

Nous retournons donc simplement un pointeur local, à un littéral de chaîne. Les littéraux de chaîne ont durée de stockage statique , rien ne pend. La fonction est vraiment la même que:

const char* f()
{
    return "test";
}

Si vous avez fait quelque chose comme ceci :

const char* f() {
    const char arr[] = "test"; // local array of char, not array of char const*
    return arr;
}

Maintenant que est UB - nous retournons un pointeur suspendu.

77
Barry

Le tableau arr a une durée de stockage local et disparaîtra à la fin de la portée. La chaîne littérale "test" est cependant un pointeur vers un emplacement de stockage statique. Stocker temporairement ce pointeur dans le tableau local arr avant de le retourner ne change rien. Ce sera toujours un emplacement de stockage statique.

Notez que si la fonction devait renvoyer un type de chaîne de style C++ au lieu d'un style C const char *, la conversion/comptabilité supplémentaire vous laisserait probablement une valeur limitée dans la durée de vie selon les règles temporaires C++.

3
user9594869