2013-04-30 1 views
0

J'essaie de déboguer un problème lié à la portée du tableau de caractères contenu dans une chaîne std :: string. J'ai posté l'exemple de code correspondant ci-dessous,Obtention d'une chaîne de caractères à partir de la copie locale de std :: string retournée

#include <iostream> 
#include <string> 

const char* objtype; 

namespace A 
{ 

std::string get_objtype() 
{ 
    std::string result; 
    std::string envstr(::getenv("CONFIG_STR")); 
    std::size_t pos1 = 0, pos2 = 0, pos3 = 0; 
    pos1 = envstr.find_first_of("objtype"); 
    if (pos1 != std::string::npos) 
    pos2 = envstr.find_first_of("=", pos1+7); 
    if (pos2 != std::string::npos) 
    { 
    pos3 = envstr.find_first_of(";", pos2+1); 
    if (pos3 != std::string::npos) 
     result = envstr.substr(pos2+1, pos3 - pos2 - 1); 
    } 
    const char* result_cstr = result.c_str(); 
    std::cerr << "get_objtype()" << reinterpret_cast<long>((void*)result_cstr) << std::endl; 
    return result; 
} 

void set_objtype() 
{ 
    objtype = get_objtype().c_str(); 
    std::cerr << "Objtype " << objtype << std::endl; 
    std::cerr << "main()" << reinterpret_cast<long>((void*)objtype) << std::endl; 
} 

} 

int main() 
{ 
    using namespace A; 
    std::cerr << "main()" << reinterpret_cast<long>((void*)objtype) << std::endl; 
    set_objtype(); 

    if (::strcmp(objtype, "AAAA") == 0) 
    std::cerr << "Do work for objtype == AAAA " << std::endl; 
    else 
    std::cerr << "Do work for objtype != AAAA" << std::endl; 
} 

Cela a été compilé et exécuté sur Mac OS 12.3 avec g ++ 4.2.1. La sortie de l'exécution est la suivante,

$ g++ -g -DNDEBUG -o A.exe A.cpp 
$ CONFIG_STR="objtype=AAAA;objid=21" ./A.exe 
main()0 
get_objtype()140210713147944 
Objtype AAAA 
main()140210713147944 
Do work for objtype == AAAA 
$ 

Mes questions sont les suivantes: La valeur du pointeur imprimé de main() et get_objtype() sont les mêmes. Est-ce dû à RVO? La dernière ligne de sortie montre que le pointeur global vers C-string est correct même si la chaîne std :: string incluse est hors de portée. Alors, quand la valeur renvoyée est-elle hors de portée et le tableau de chaînes supprimé? Toute aide de la communauté est appréciée. Merci.

+0

La chaîne renvoyée dans get_objtype() est détruite juste après l'instruction. c'est-à-dire après avoir frappé le point-virgule. C'est juste que l'adresse pointée par objtype n'est pas écrasée par d'autres données. Par conséquent, vous voyez toujours la valeur "AAAA". – Jagannath

+0

BTW, qu'est-ce que vous essayez de réaliser avec cet exemple? À moins que vous ne fassiez quelque chose de différent, simplifiez et simplifiez le code. – Jagannath

+0

J'essaie de comprendre un morceau de code existant. –

Répondre

1

La valeur du pointeur ne change pas, mais la mémoire vers laquelle elle pointe ne fait plus partie d'une chaîne.

objtype est invalide sur la ligne juste après l'avoir définie dans set_objtype() parce que le résultat de get_objtype() n'est pas enregistré n'importe où, de sorte que le compilateur est libre de le tuer ici et ensuite.

Cela peut fonctionner, mais c'est accéder à une mémoire invalide, donc c'est un code invalide et si vous comptez sur des choses comme ça, vous finirez par rencontrer de gros problèmes.

+0

Merci. Alors, le compilateur créera-t-il une chaîne temporaire avant d'appeler c_str()? –

+0

Il existe une chaîne anonyme "existante" jusqu'au point-virgule sur la ligne 'objtype = get_objtype(). C_str();' La méthode get renvoie une chaîne réelle (sur la pile). – John3136

0

Vous devriez regarder le désassemblage en utilisant objdump pour vérifier si son RVO. Mais, d'après les expériences que j'ai faites (rendant le résultat global et en faisant des copies), il semble que c_str soit compté comme référence.

Questions connexes