Je ne suis pas un programmeur C, je ne connais donc pas très bien C-string, mais je dois maintenant utiliser une bibliothèque C. Voici donc une version abrégée de mon code pour illustrer mon problème:
char** ReadLineImpl::my_completion () {
char* matches[1];
matches[0] = "add";
return matches;
}
Je reçois un avertissement:
Avertissement - adresse de la mémoire de pile associée à la variable locale 'correspond' renvoyée
Et mon application ne semble pas fonctionner correctement (peut-être à cause de cet avertissement).
Quel est l'avertissement et va-t-il causer des problèmes?
La variable char* matches[1];
est déclarée sur la pile et elle sera automatiquement libérée lorsque le bloc actuel sortira de la portée.
Cela signifie que lorsque vous renvoyez matches
, la mémoire réservée à matches
sera libérée et votre pointeur indiquera quelque chose que vous ne souhaitez pas.
Vous pouvez résoudre ce problème de nombreuses manières, et certaines d’entre elles sont:
Déclarez matches[1]
en tant que static
: static char* matches[1];
- this Allouera de l'espace pour matches
sur le tas (cela peut vous mordre si vous L'utilisez de manière inappropriée, car toutes les instances de la fonction my_completion
.__ partageront la même variable matches
.
Allouez de l'espace dans la fonction appelant et transmettez-le à my_completion
Function: my_completion(matches)
:
char* matches[1];
matches = my_completion(matches);
// ...
char** ReadLineImpl::my_completion (char** matches) {
matches[0] = "add";
return matches;
}
Allouez de l'espace dans la fonction appelée sur le tas (en utilisant malloc
, calloc
et amis) et transmettez la propriété à la fonction appelant, qui devra libérer cet espace lorsqu'elle n'est plus nécessaire (en utilisant free
).
Lorsque vous renvoyez le tableau matches
, vous retournez l'adresse du premier élément. Ceci est stocké sur la pile dans my_completion
. Une fois que vous retournez de my_completion
cette mémoire est récupérée et sera (très probablement) éventuellement réutilisée pour autre chose, écrasant les valeurs stockées dans matches
- et oui, c'est peut-être pourquoi votre application ne fonctionne pas maintenant, ce sera probablement une fois que vous aurez corrigé un autre problème, ou que vous l'avez modifié un peu, ou autre chose, car il ne s'agit pas d'un de ces petits avertissements que vous pouvez ignorer en toute sécurité.
Vous pouvez résoudre ce problème de différentes manières. La plus évidente consiste simplement à utiliser std::vector<char *>
[ou encore mieux std::vector<std::string>
]:
std::vector<std::string> ReadLineImpl::my_completion ()
{
std::vector<std::string> strings;
strings.Push_back("add");
return strings;
}
Edit: Donc, si la bibliothèque nécessite un char **
conformément à l'interface readline
, utilisez ceci:
char** ReadLineImpl::my_completion ()
{
char **matches = static_cast<char **>malloc(1 * sizeof(char *));
matches[1] = "add";
return matches;
}
Problème résolu!
changement
char* matches[1];
à
char *matches = new matches[1];
Il vaut mieux allouer de la mémoire dans le tas pour dans ce cas en utilisant:
int* someDataForParams(void *_params) {
...
int* charCounts = calloc(96, sizeof(char*));
...
return charCounts;
}
96 est juste une longueur de chaîne (juste un nombre magique)