Использование 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
будет освобожден, и указатель будет указывать на то, что вы не хотите.
вы можете решить многими способами, и некоторые из них являются:
объявить
matches[1]
asstatic
:static char* matches[1];
- это выделит место дляmatches
на куче (это может укусить вас, если вы использовать его unappropriately, как все экземпляры поделюсь жеmatches
переменной).-
выделите место в функции вызывающего абонента и передайте его
my_completion
функция:my_completion(matches)
:char* matches[1]; matches = my_completion(matches); // ... char** ReadLineImpl::my_completion (char** matches) { matches[0] = "add"; return matches; }
выделить место в вызываемой функции в куче (используя
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;
}
проблема решена!
используйте heap вместо stack
лучше выделить память в куче для в этом случае использование:
int* someDataForParams(void *_params) {
...
int* charCounts = calloc(96, sizeof(char*));
...
return charCounts;
}
96-это просто длина строки(просто магическое число)