Gebruik van C-string geeft waarschuwing: “Adres van stackgeheugen geassocieerd met lokale variabele geretourneerd”

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 matchesretourneert, geheugen gereserveerd voor matcheswordt vrijgemaakt en dat uw aanwijzer naar iets wijst dat u niet wilt.

Je kunt dit op veel manieren oplossen, en sommige zijn:

  1. Declareer matches[1]als static: static char* matches[1];– dit
    zal ruimte toewijzen voor matchesin de statische ruimte en niet op de stapel (dit kan je bijten als je
    gebruik het ongepast, aangezien alle instanties van de functie my_completion
    zal dezelfde matchesvariabele delen).

  2. 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;
    }
    
  3. Wijs ruimte toe in de aangeroepen functie op heap (met behulp van malloc, callocen 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 van free).


Antwoord 2, autoriteit 17%

Als je de array matchesretourneert, 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 readlineinterface, 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];

Other episodes