De retour « c_str » d'une fonction
-
27-09-2019 - |
Question
Ceci est d'une petite bibliothèque que je trouve en ligne:
const char* GetHandStateBrief(const PostFlopState* state)
{
static std::ostringstream out;
// ... rest of the function ...
return out.str().c_str()
}
Dans mon code que je fais ceci:
const char *d = GetHandStateBrief(&post);
std::cout<< d << std::endl;
Maintenant, tout d'abord d
contenait des ordures. Je me suis alors rendu compte que la chaîne C que je reçois de la fonction est détruite lorsque la fonction retourne parce que std::ostringstream
est allouée sur la pile. J'ai donc ajouté:
return strdup( out.str().c_str());
Et maintenant, je peux obtenir le texte dont j'ai besoin de la fonction.
J'ai deux questions:
-
Suis-je comprendre cela correctement?
-
Je remarqué plus tard que
out
(de typestd::ostringstream
) a été affecté au stockage statique. Est-ce que cela veut dire pas que l'objet est censé rester en mémoire jusqu'à ce que le programme se termine de? Et si oui, alors pourquoi ne peut pas la chaîne est accessible?
La solution
strdup alloue une copie de la chaîne sur le tas, que vous devez libérer manuellement plus tard (avec free()
je pense). Si vous avez l'option, il serait préférable de std::string
de retour.
Le stockage statique de out
ne aide, parce que .str()
retourne un std::string
temporaire, qui est détruit lorsque les sorties de fonction.
Autres conseils
Vous avez raison out
est une variable statique allouée sur le segment de données. Mais out.str()
est temporaire alloué sur la pile. Alors, quand vous faites return out.str().c_str()
vous retournez un pointeur vers une pile de données de temporaires de internes. Notez que même si une chaîne est pas une variable de la pile, c_str
est « seulement accordé rester inchangé jusqu'au prochain appel à une fonction de membre non constante de l'objet chaîne. »
Je pense que vous avez frappé sur une solution raisonnable, en supposant ne pouvez pas retourner une chaîne.
strdup () renvoie un pointeur char * qui pointe vers la mémoire sur le tas. Vous devez libérer () quand vous avez terminé, mais oui, cela fonctionnera.
La std::ostringstream out
variable locale statique n'a pas de sens dans ce cas, à moins que le std :: string retourné a également été statique de votre observation montre être pas vrai.
Dans GetHandStateBrief
, out
variable ne doit pas être statique. Vous avez besoin d'un static string
explicite pour remplacer le temporaire qui a été créé dans votre appel initial à out.str()
:
static std::string outStr;
std::ostringstream out;
... rest of function ...
outStr = out.str();
return outStr.c_str();