2016-02-12 1 views
1

Pour cette fonction, je dois retourner une variable char *, avant de la renvoyer, je l'imprime et l'imprime bien. qu'est-il arrivé à la variable qui rend la variable de retour erronée et pourquoi?Renvoi de caractères erronés, impression incorrecte, retour incorrect (C++)

La fonction:

const char* NameErrorException::what() const throw() 
{ 
    std::string str = "NameErrorException: name \'"; 
    str += _name; 
    str += "\' is not defimed"; 
    std::cout << str.c_str()<< std::endl; //Prints good 
    return str.c_str(); 
} 

Le code d'impression:

catch (std::exception& ex) 
{ 
    //Prints something like "▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌♀·┘v♦" 
    std::cout << ex.what() << std::endl; 
} 

(NameErrorException exception d'Héritier)

Merci!

+7

Possible [en double] (http://stackoverflow.com/questions/6456359/what-is-stdstringc-str-lifetime). –

+1

str est une variable locale et comme toutes les variables locales, elle sera collectée à la fin de la méthode. Si vous renvoyez un pointeur valide dans la méthode, il ne sera pas valide en dehors de la méthode s'il provient d'une variable locale, sauf si vous lui avez alloué l'espace. Cela vaut également pour les pointeurs renvoyés comme c_str() sauf si vous avez des raisons de penser que vous êtes renvoyé un pointeur qui ne sera pas détruit plus tard, ce qui n'est certainement pas votre cas. – Neil

+0

Peut-être pas nécessairement un doublon, mais une réponse à ce problème est là pour sûr. –

Répondre

3

Votre chaîne str sera détruite une fois que vous aurez quitté la fonction. Le pointeur renvoyé n'est donc pas valide, car il pointe vers la mémoire gérée par l'objet. Si l'objet est détruit, il libèrera de nouveau ce souvenir.

Rendez str membre de l'exception et initialisez-le dans le constructeur. Que votre what() renverra un pointeur valide (tant que l'objet d'exception est valide).

#include <string> 
#include <iostream> 

class NameErrorException : public std::exception 
{ 
    std::string m_what; 
public: 
    NameErrorException(std::string name) 
     :m_what("NameErrorException: name \'" + name + "\' is not defined") 
    { 
    } 

    const char* what() const throw() override 
    { 
     return m_what.c_str(); 
    } 
}; 


int main() 
{ 
    try 
    { 
     throw NameErrorException("TEST"); 
    } 
    catch (std::exception& ex) 
    { 
     std::cout << ex.what() << std::endl; 
    } 
} 

Voir ici: http://coliru.stacked-crooked.com/a/878d5835db998300

+0

bien, c'est du travail, merci! – swis11

+0

La construction de 'std :: string' peut générer une exception. Ce n'est pas forcément une bonne idée d'avoir un type d'exception qui peut être lancé au fur et à mesure de sa construction. Le résultat peut être une exception inattendue en cours de levée. – Peter

+0

@Peter Où recommanderiez-vous de construire la chaîne? 'what()' est 'const'. Je suis d'accord sur le fait que cela pourrait causer des problèmes mais si 'std :: string' se lance, j'attends aussi d'autres problèmes plus sérieux. –

0

string::c_str() renvoie un pointeur vers la mémoire interne utilisée.

votre objet string est une variable locale, il est détruit à la fin de votre appel de fonction, conduisant à un accès mémoire invalide par la suite.

vous devez utiliser strcpy dans un bloc de mémoire nouvellement généré ou renvoyer directement un objet std::string à la place, ce qui serait l'option la plus sûre.