Question

Je suis toujours confus au sujet de retourner une chaîne littérale ou une chaîne à partir d'une fonction. On m'a dit qu'il pourrait y avoir fuite de mémoire parce que vous ne savez pas quand la mémoire sera effacée?

Par exemple, dans le code ci-dessous, comment mettre en œuvre foo() de manière à rendre la sortie du code est « Bonjour tout le monde »?

void foo (       )              // you can add parameters here.
{

}

int main ()
{
    char *c;
    foo (    );
    printf ("%s",c);
    return 0;
}

En outre, si le type de retour de foo() n'est pas vide, mais vous pouvez revenir char*, que doit-il être?

Était-ce utile?

La solution

Je suppose que nous ne pouvons pas modifier principale. Pour faire fonctionner votre programme sans une fuite, vous devez avoir quelque chose de stockage statique:

void foo(char*& pC)  // reference
{
    static char theString[] = "thingadongdong";

    pC = theString;
}

Mais vraiment, ce n'est pas très conventionnel code C ++. Vous souhaitez utiliser std::string et std::cout, de sorte que vous ne faites pas Vous à vous soucier de la mémoire:

std::string foo(void)
{
    return "better thingadongdong";
}

int main(void)
{
    // memory management is done
    std::cout << foo() << std::endl;
}

Si vous vous demandez si quelque chose doit être manuellement désallouée, cela se fait mal.

Autres conseils

Depuis l'ancienne utilisation de char * est dépréciée, pouvez-vous pas simplement utiliser une chaîne?

const char* func1 () {return "string literal";}

string func2 () {return "another string literal";}

Ces deux fonctionnent très bien, sans avertissement du compilateur.

Cependant

char* func3 () {return "yet another string literal";}

ne compilera pas du tout. Pas plus

char* func4 () {return &"a ref to a string literal?";}

Stroustrup dit dans "Le langage C ++ de programmation" (troisième édition):

»est attribué statiquement Une chaîne littérale de sorte qu'il est sûr de retourner une à partir d'une fonction.

const char* error_message (int i)`
{
//...
return "range error";
}

La mémoire contenant erreur de plage ne va pas disparaître après un appel de error_messages (). "

Ainsi, chaque chaîne de caractères dans un programme est affecté dans son propre petit morceau de mémoire qui dure pendant toute la durée du programme (à savoir est allouée de manière statique). Mettre le const devant le char * permet au compilateur que vous ne l'intention (et ne peut pas) modifier cette chaîne petit morceau de la mémoire du littéral qui pourrait être dangereux, donc ils ont laissé cette diapositive d'affectation malgré que la conversion de chaîne littérale char * est dépréciée.

De retour au lieu d'une chaîne doit copier la chaîne littérale dans un objet de type chaîne, de la mémoire que l'appelant est responsable.

Quoi qu'il en soit, il n'y a pas de fuites de mémoire: chaque chaîne littérale obtient son propre morceau de mémoire qui est nettoyé à la fin du programme; retour à const char * renvoie un pointeur sur un morceau de littéral de la mémoire (sachant que vous ne pouvez pas le modifier); et le retour à une chaîne fait une copie dans un objet de chaîne existante dans le code de l'appelant qui est nettoyé par l'appelant.

Bien qu'il semble un peu laid sage notation, je devine qu'ils ont quitté le const char * pour garder l'alternative pas cher (impliquant pas de copies).

  

Je suis toujours confus au sujet de retourner une chaîne littérale ou une chaîne à partir d'une fonction.

Immuable, chaîne de caractères

Si je comprends bien, vous êtes sûr de retourner une chaîne de caractères directement si le type de retour est déclaré const, déclarer que la chaîne ne vise pas à être modifié. Cela signifie que vous ne devez pas vous soucier de la durée de vie de la chaîne / fuites de mémoire.

Mutable, chaîne non littérale

Cependant, si vous avez besoin d'une chaîne que vous pouvez changer en place, vous devez tenir compte de la durée de vie de la chaîne et la taille de l'allocation de mémoire dans laquelle il est stocké. Cela devient un problème, puisque vous ne pouvez plus revenir allègrement la même chaîne contenant une mémoire pour chaque appel de la fonction, car une utilisation antérieure aurait pu modifier le contenu de cette mémoire, et / ou peut encore être utilisé. D'où un nouveau morceau de mémoire doit être allouée pour contenir la chaîne retournée.

est où le potentiel d'une fuite se produit, et où le choix doit être fait sur l'endroit où l'allocation et la répartition devrait se produire. Vous pourriez avoir la fonction elle-même allouer la mémoire et de l'état dans la documentation que cela se produit et que celui-ci stipule que l'appelant doit libérer la mémoire quand il est plus nécessaire (empêchant une fuite). Cela signifie que la fonction peut simplement renvoyer un char *.

L'autre option consiste à faire passer dans une mémoire pour la fonction qui a été alloué par l'appelant, et avoir la place de la fonction de la chaîne à l'intérieur de cette mémoire. Dans ce cas, l'appelant les deux alloue et est responsable de la libération que la mémoire.

Enfin, je l'ai mentionné que la taille de la mémoire et la chaîne doivent être gérés en utilisant une chaîne mutable. L'allocation doit être à la fois assez grand pour la chaîne initialement fixé par la fonction et aussi pour les éventuelles modifications qui sont apportées après la fonction, avant que la mémoire est libérée. A défaut de faire cela correctement peut causer un débordement de mémoire tampon en écrivant une chaîne longue pour tenir dans la mémoire allouée initialement; ce qui est extrêmement dangereux pour la santé et la sécurité de votre programme. Il peut causer des bugs et des failles de sécurité qui sont extrêmement difficiles à repérer. (Depuis la source de l'erreur - le trop-plein - peut être loin des symptômes observés lorsque le programme échoue)

Quelque chose comme ceci:

void foo(char ** pChar)
{
    // Make sure the string is shorter
    // than the buffer
    *pChar = new char[256];
    strcpy(*pChar,"Hello World!");
}

Ensuite, appelez comme ceci:

foo(&c);

Comme mentionné dans le commentaire, faites attention à la chaîne que vous stockez est plus petite que la mémoire tampon ou vous obtiendrez un débordement de pile ...! (Jeu de mots)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top