我不是C程序员,所以我对C-string并不熟悉但新的我必须使用C库,所以这里是我的代码的缩短版本来演示我的问题:
char** ReadLineImpl::my_completion () {
char* matches[1];
matches[0] = "add";
return matches;
}
我收到警告:
警告 - 与本地变量“匹配”返回相关联的堆栈内存地址
我的应用程序似乎没有正常工作(可能是因为这个警告)。
警告是什么,是否会引起任何问题?
答案 0 :(得分:32)
变量char* matches[1];
在堆栈上声明,当当前块超出范围时,它将自动释放。
这意味着当您返回matches
时,将释放为matches
保留的内存,并且您的指针将指向您不想要的内容。
你可以通过多种方式解决这个问题,其中一些是:
将matches[1]
声明为static
:static char* matches[1];
- 此
将在堆上为matches
分配空间(如果你这可能会咬你
因为my_completion
的所有实例都起作用,所以不正当地使用它
将共享相同的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
)。
答案 1 :(得分:8)
当您返回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;
}
编辑:因此,如果库根据readline
界面需要char **
,那么请使用:
char** ReadLineImpl::my_completion ()
{
char **matches = static_cast<char **>malloc(1 * sizeof(char *));
matches[1] = "add";
return matches;
}
问题解决了!
答案 2 :(得分:0)
变化
char* matches[1];
到
char *matches = new matches[1];
答案 3 :(得分:0)
最好通过使用:
在堆中为这种情况分配内存int* someDataForParams(void *_params) {
...
int* charCounts = calloc(96, sizeof(char*));
...
return charCounts;
}
96只是一个字符串长度(只是一个幻数)