Ik ben geen C-programmeur, dus ik ben niet zo bekend met C-string, maar nu moet ik een C-bibliotheek gebruiken, dus hier is een verkorte versie van mijn code om mijn probleem aan te tonen:
char** ReadLineImpl::my_completion () {
char* matches[1];
matches[0] = "add";
return matches;
}
Ik krijg deze waarschuwing:
Waarschuwing – adres van stapelgeheugen dat is gekoppeld aan lokale variabele ‘overeenkomsten’ geretourneerd
En mijn programma lijkt niet goed te werken (misschien vanwege de bovengenoemde waarschuwing).
Wat houdt de waarschuwing in? en zal het problemen veroorzaken?
Antwoord 1, autoriteit 100%
Variabele char* matches[1];
wordt op de stapel gedeclareerd en wordt automatisch vrijgegeven wanneer het huidige blok buiten het bereik valt.
Dit betekent dat wanneer u matches
retourneert, geheugen gereserveerd voor matches
wordt vrijgemaakt en dat uw aanwijzer naar iets wijst dat u niet wilt.
Je kunt dit op veel manieren oplossen, en sommige zijn:
-
Declareer
matches[1]
alsstatic
:static char* matches[1];
– dit
zal ruimte toewijzen voormatches
in de statische ruimte en niet op de stapel (dit kan je bijten als je
gebruik het ongepast, aangezien alle instanties van de functiemy_completion
zal dezelfdematches
variabele delen). -
Wijs ruimte toe in de aanroepfunctie en geef deze door aan
my_completion
functie:my_completion(matches)
:char* matches[1]; matches = my_completion(matches); // ... char** ReadLineImpl::my_completion (char** matches) { matches[0] = "add"; return matches; }
-
Wijs ruimte toe in de aangeroepen functie op heap (met behulp van
malloc
,calloc
en vrienden) en geef het eigendom door aan de aanroepfunctie, die maak de toewijzing van deze ruimte ongedaan wanneer deze niet meer nodig is (met behulp vanfree
).
Antwoord 2, autoriteit 17%
Als je de array matches
retourneert, is wat je retourneert het adres van het eerste element. Dit wordt opgeslagen op de stapel in my_completion
. Zodra u terugkeert van my_completion
, wordt dat geheugen teruggewonnen en zal (hoogstwaarschijnlijk) uiteindelijk worden hergebruikt voor iets anders, waarbij de waarden worden overschreven die zijn opgeslagen in matches
– en ja, dat kan heel goed zijn waarom je applicatie niet werkt – als het nu niet goed is, zal het waarschijnlijk zijn als je een aantal andere problemen hebt opgelost, of het een beetje hebt veranderd, of iets anders, want dit is niet een van die kleine waarschuwingen die je kunt veilig negeren.
Je kunt dit op verschillende manieren oplossen. Het meest voor de hand liggend is om in plaats daarvan std::vector<char *>
[of beter nog std::vector<std::string>
] te gebruiken:
std::vector<std::string> ReadLineImpl::my_completion ()
{
std::vector<std::string> strings;
strings.push_back("add");
return strings;
}
Bewerken: Dus, als de bibliotheek een char **
vereist volgens de readline
interface, gebruik dan dit:
char** ReadLineImpl::my_completion ()
{
char **matches = static_cast<char **>malloc(1 * sizeof(char *));
matches[1] = "add";
return matches;
}
Probleem opgelost!
Antwoord 3
Gebruik de hoop in plaats van stapel
Het is beter om het geheugen in de hoop voor deze zaak toe te wijzen door middel van:
int* someDataForParams(void *_params) {
...
int* charCounts = calloc(96, sizeof(char*));
...
return charCounts;
}
96 is slechts een touwlengte (slechts een magisch getal)
Antwoord 4
Wijzigen
char* matches[1];
Naar
char *matches = new matches[1];