Использование C-string: "адрес стековой памяти, связанной с возвращаемой локальной переменной"

Я не программист C, поэтому я не знаком с C-string, но новый я должен использовать библиотеку C, поэтому вот сокращенная версия моего кода, чтобы продемонстрировать мою проблему:

char** ReadLineImpl::my_completion () {

    char* matches[1];


    matches[0] = "add";

    return matches;

}

Я получаю предупреждение:

Warning-адрес стековой памяти, связанной с локальной переменной "matches", возвращается

и мое приложение, похоже, работает неправильно (может быть, из-за этого предупреждения).

что такое предупреждение и это вызовет какие-либо проблемы?

4 ответов


переменная char* matches[1]; объявляется в стеке, и он будет автоматически освобожден, когда текущий блок выходит из рамок.

это означает, когда вы вернетесь matches, объем памяти, зарезервированный для matches будет освобожден, и указатель будет указывать на то, что вы не хотите.

вы можете решить многими способами, и некоторые из них являются:

  1. объявить matches[1] as static: static char* matches[1]; - это выделит место для matches на куче (это может укусить вас, если вы использовать его unappropriately, как все экземпляры поделюсь же matches переменной).

  2. выделите место в функции вызывающего абонента и передайте его my_completion функция:my_completion(matches):

    char* matches[1];
    matches = my_completion(matches);
    
    // ...
    
    char** ReadLineImpl::my_completion (char** matches) {
         matches[0] = "add";
    
         return matches;
    }
    
  3. выделить место в вызываемой функции в куче (используя malloc, calloc, и друзья) и передать право собственности на вызывающую функцию, которая должна будет освободить это пространство, когда это больше не нужно (используя free).


когда вы возвратитесь matches массив, что вы возвращаете-это адрес первого элемента. Это хранится в стеке внутри my_completion. Как только вы вернетесь из my_completion эта память восстанавливается и (скорее всего) в конечном итоге будет использоваться для чего-то другого, перезаписывая значения, хранящиеся в matches - и да, возможно, именно поэтому ваше приложение не работает - если это не прямо сейчас, это, вероятно, будет после того, как вы исправили некоторые другие проблемы, или изменили его немного, или что-то еще иначе, потому что это не одно из тех маленьких предупреждений, которые можно смело игнорировать.

вы можете исправить это несколькими способами. Самое очевидное-просто использовать std::vector<char *> [или std::vector<std::string>] вместо:

std::vector<std::string> ReadLineImpl::my_completion ()
{
    std::vector<std::string> strings;
    strings.push_back("add");
    return strings;
}

Edit: Итак, если библиотека требует char ** на readline интерфейс,то используйте этот:

char** ReadLineImpl::my_completion ()
{
    char **matches = static_cast<char **>malloc(1 * sizeof(char *));
    matches[1] = "add";
    return matches;
}

проблема решена!


изменить

char* matches[1];

to

char *matches = new matches[1];

используйте heap вместо stack

лучше выделить память в куче для в этом случае использование:

int* someDataForParams(void *_params) {

    ...
    int* charCounts = calloc(96, sizeof(char*));
    ...

    return charCounts;
}

96-это просто длина строки(просто магическое число)