C Avertissement: la Fonction renvoie l'adresse d'une variable locale
La fonction suivante prend la argv[0] argument qui contient l'appel de chemin d'accès de l'application et remplace le dernier bit jusqu'à ce qu'il rencontre un "/" avec le nom de la nouvelle application que je veux spawn qui se trouve dans le même dossier.
BTW: je suis déclarant mondiale argv variable de sorte que la fonction peut y avoir accès parce que je n'ai pas envie de passer l'info à chaque appel de fonction.
Quand je compile mon code, tout semble fonctionner, mais j'ai l'avertissement ci-dessus.
Je sais que je suis en déclarant la variable et que dès que la fonction retourne il sera détruit.
D'être un débutant programmeur en C, je voulais savoir quel est le plus élégant/façon la plus simple de résoudre ce problème serait?
Devrais-je passer un pointeur à la fonction ou à la fonction malloc de la mémoire?
char *returnFullPath()
{
char pathToApp[strlen(argv[0])+1];
strcpy(pathToApp, argv[0]);
int path_length = strlen(argv[0]);
while (pathToApp[path_length] != '/')
{
path_length--;
}
if (path_length > 2)
pathToApp[path_length+1] = 'char *returnFullPath()
{
char pathToApp[strlen(argv[0])+1];
strcpy(pathToApp, argv[0]);
int path_length = strlen(argv[0]);
while (pathToApp[path_length] != '/')
{
path_length--;
}
if (path_length > 2)
pathToApp[path_length+1] = '\0';
else
pathToApp[0] = '\0';
//length of getcwd + length of pathtoapp + 1 for zero plus 6 for "bidbot"
char bidbotPath[strlen(getcwd(NULL,0)) + strlen(pathToApp) + 1 + 6];
sprintf(bidbotPath, "%s/%sbidbot", getcwd(NULL,0), pathToApp);
return bidbotPath;
}
';
else
pathToApp[0] = 'char *returnFullPath()
{
char pathToApp[strlen(argv[0])+1];
strcpy(pathToApp, argv[0]);
int path_length = strlen(argv[0]);
while (pathToApp[path_length] != '/')
{
path_length--;
}
if (path_length > 2)
pathToApp[path_length+1] = '\0';
else
pathToApp[0] = '\0';
//length of getcwd + length of pathtoapp + 1 for zero plus 6 for "bidbot"
char bidbotPath[strlen(getcwd(NULL,0)) + strlen(pathToApp) + 1 + 6];
sprintf(bidbotPath, "%s/%sbidbot", getcwd(NULL,0), pathToApp);
return bidbotPath;
}
';
//length of getcwd + length of pathtoapp + 1 for zero plus 6 for "bidbot"
char bidbotPath[strlen(getcwd(NULL,0)) + strlen(pathToApp) + 1 + 6];
sprintf(bidbotPath, "%s/%sbidbot", getcwd(NULL,0), pathToApp);
return bidbotPath;
}
OriginalL'auteur Frank Vilea | 2011-08-01
Vous devez vous connecter pour publier un commentaire.
Certains autres réponses suggèrent que vous malloc quelque chose et de le retourner. C'est une mauvaise pratique dans le même sens qu'en C++, quand vous quelque chose de nouveau dans une fonction et que l'appelant est censé supprimer (qui a la propriété?)
Il ya une raison que beaucoup de C Api ont le format de:
Ce qui signifie que l'APPELANT fournit le tampon et combien de temps il est. C'est l'appelant responsabilité d'affecter et de répartir ce tampon et la fonction que vous devriez l'utiliser, et de vérifier que vous n'allez pas le dépassement de la longueur.
Ne pas malloc et retour. C'est juste d'avoir des ennuis.
ces bons conseils décompose lorsque l'appelant ne peut pas attendre de savoir comment grand d'un tampon à allouer.
De nombreuses bibliothèques C et les fonctions, y compris ceux de POSIX, allouer-et-retour pour precicely la raison David Heffernan donne. Meilleur conseil: "ne faites pas d'hypothèses sur l'appel-conventions.", jumelé avec "utiliser un débogueur mémoire".
OK, il peut y avoir des exceptions, mais la réponse ci-dessus de l'OMI devrait être la règle générale. Et dans la plupart des cas, les stratégies que j'ai mentionnés faire le travail. FWIW, si la fonction alloue, il doit connaître la taille trop.
Merci si un court exemple de code serait utile
OriginalL'auteur Moo-Juice
Remplacer
avec
De cette façon, votre variable est allouée sur le tas et pas sur la pile, de sorte qu'il ne sera pas supprimé après la fonction renvoie.
Je sais, j'ai corrigé 🙂
Grâce Luchian, je suis encore à apprendre à propos de la fonction malloc. J'ai essayé ton code et il fonctionne. C'est ce que j'ai déjà créé moi-même: "char * bidbotPath = malloc((sizeof(char))*(strlen(getcwd(NULL,0)) + strlen(pathToApp) + 1 + 6)); Vos looks nettement plus propre. Mais comment peut-il être que vous n'êtes pas à l'aide de l'opérateur sizeof? J'ai pensé qu'il doit être utilisée lors de mallocing? Merci encore pour clarifier!!
Je n'ai pas utiliser sizeof car la taille d'un char est TOUJOURS 1. Ceci est garanti par la norme. Il serait redondant de dire malloc(sizeof(char)*(strlen(getcwd(NULL,0)) + strlen(pathToApp) + 1 + 6)).
OriginalL'auteur Luchian Grigore
Si possible, il est toujours préférable de la fonction un pointeur vers la mémoire dans laquelle la valeur retournée peut être écrit. Je le dis parce que vous permettez à vos clients (les appelants de la fonction) le choix de la localisation de la mémoire: sur la pile ou le tas, ou peut-être même un endroit plus exotique.
Maintenant, la bosse, c'est le si possible clause. Parfois, la taille de la mémoire ne peut être déterminée lors de la mise en œuvre de la fonction. Un exemple typique serait une fonction que la chaîne se terminant par null. Quand vous venez à travers ce scénario, vous êtes généralement préférable de recourir à l'allocation de la mémoire sur le tas à l'intérieur de la fonction, et en exigeant que vos clients pour libérer la mémoire quand ils sont fait avec elle.
OriginalL'auteur David Heffernan
Comme une première chose à dire, l'avertissement que vous obtenez, pourrait être considéré une erreur. Tout subsecuent appel à une nouvelle fonction, ne manquera pas d'écrire sur la mémoire qui a été tenue les informations que vous souhaitez retourner. Ceci étant dit, il ya un couple de façons de travailler à cette question à travers.
Client-face de la propriété
On pourrait être, comme Moo-Jus suggéré, ajouter quelques paramètres à votre invocation, la délégation de la responsabilité de la mise à la persistants après l'appel de fonction.
et avant que vous avez terminé, copiez le résultat dans le paramètre de sortie avec un appel à strncpy (http://www.cplusplus.com/reference/cstring/strncpy/).
De cette façon, vous vous assurez la fonction de l'appelant, est le propriétaire de la mémoire, de l'allocation et de l'allocation. Et que vous n'essayez pas d'utiliser des nations unies-mémoire allouée.
Fournisseur-verso de la propriété
Il y a, cependant, une autre approche, également acceptés pour cette langue. Et c'est la seule utilisée, par exemple, par la stdio.h la bibliothèque. Si vous voulez ouvrir un fichier, vous utilisez le FICHIER de structure, comme un pointeur. Dans ce cas, la stdio nous fournit les fonctions fopen et fclose, qui alloue les ressources, et de l'autre que de les attribue. Cela rend l'utilisation d'un concept de Type Abstrait de Données, ce qui est la chose la plus proche d'un objet, nous allons jamais voir dans la programmation structurée. Voir cette pour plus de détails sur les ADTs. Dans ce cas, une complète ADT semble absurde overkill pour ce que vous faites, mais va de pair avec l'idée.
Pour ce cas, nécessite à la fois des fonctions d'allocation et de répartition.
De cette façon, vous pouvez malloc l'exacte quantité de mémoire dont vous avez besoin
Liés à votre question, je voudrais faire quelques commentaires.
OriginalL'auteur coya
Quand un retour de la fonction, la variable locale sera libéré (libéré), et la mémoire sera utilisée pour autre chose. Si vous retourner l'adresse d'une variable locale, elle peut (et doit) cause du problème.
Il y a deux façons de résoudre ce.
1) utilisation
static
variable. variable locale statique ne sont pas libérés sur la sortie de la fonction.MAIS! il ne fonctionnera pas avec une longueur variable.
2) Utiliser
malloc
et vous devriez appeler
free(bidbotPath)
après toutes les utilisations de celui-ci.static
variable peuvent être retournés, mais la valeur pointée va changer pour tout le monde qui utilise un pointeur de fonction chaque fois que la fonction est appelée. C'est très rarement ce que vous voulez, et encore moins rarement ce que vous devriez vouloir.suggérez-vous qu'il serait mieux de passer un pointeur vers la fonction?
Non, je dis à l'aide d'un
static
variable n'est pas une solution. En passant un pointeur à remplir et retourner un pointeur fraîchement malloc avais emplacement sont deux solutions valables, il y a peut être même plus.OriginalL'auteur J-16 SDiZ
Vous devez attribuer
bidbotPath
variable de la mémoire dynamiquement à l'aide demalloc
oucalloc
. Ensuite, assurez-vous que le code appelant la fonction est réellement libérer le malloc ed la mémoire de votre retour. C'est une pratique courante, et d'un commun langage C les fonctions qui renvoient des pointeurs vers un "produit" tableau.OriginalL'auteur Diego Sevilla
Comme BidotPath est déclaré dans le champ d'application de la fonction du corps comme une pile normale de la variable, il disparaît lorsque la fonction retourne. Alors que votre programme peut travailler maintenant, c'est juste par chance et qu'il peut commencer à échouer plus tard si d'autres code réutilise la vieille pile de l'avant de votre appelant n'.
Vous pouvez déclarer bobotPath statique, qui la maintient autour, mais empêche la fonction de thread-safe. Vous pourriez faire un malloc de la bonne longueur et de retour que pour garder la fonction thread-safe, mais, mais, l'appelant aurait besoin pour libérer de la mémoire pour éviter les fuites. le Mieux serait de fournir un tableau de char, et de la longueur, de mettre les données en argument de ta fonction. Pense snprintf() ici. À l'intérieur de l'utilisation de strncpy(), et d'autres routines, à copier à la cible, mais sachez que strncat() peut ne pas être sans danger pour vous.
Aussi, votre code doit composer avec le fait qu'il pourrait ne pas être une barre oblique dans argv[0]... juste le nom de l'exécutable.
Pas tout à fait ce que vous avez besoin, mais voici un code que j'ai utilisé. Je laisse comme un exercice à l'étudiant d'obtenir ce dont vous avez besoin:
OriginalL'auteur Gilbert
lorsque vous essayez d'appeler n'importe quelle fonction automatiquement mémoire alloué sur la pile,mais normalement après l'exécution de la définition de la fonction frame de pile est mise au rebut de la pile de la mémoire comme spécialement si vous voulez que votre fonction de l'adresse de retour alors faire des variables qui sont utilisées dans la définition de la fonction statique
OriginalL'auteur rohit