使用C-string:“返回与本地变量关联的堆栈内存的地址”

时间:2013-08-04 08:23:07

标签: c++ pointers c-strings

我不是C程序员,所以我对C-string并不熟悉但新的我必须使用C库,所以这里是我的代码的缩短版本来演示我的问题:

char** ReadLineImpl::my_completion () {

    char* matches[1];


    matches[0] = "add";

    return matches;

}

我收到警告:

  

警告 - 与本地变量“匹配”返回相关联的堆栈内存地址

我的应用程序似乎没有正常工作(可能是因为这个警告)。

警告是什么,是否会引起任何问题?

4 个答案:

答案 0 :(得分:32)

变量char* matches[1];在堆栈上声明,当当前块超出范围时,它将自动释放。

这意味着当您返回matches时,将释放为matches保留的内存,并且您的指针将指向您不想要的内容。

你可以通过多种方式解决这个问题,其中一些是:

  1. matches[1]声明为staticstatic char* matches[1]; - 此 将在堆上为matches分配空间(如果你这可能会咬你 因为my_completion的所有实例都起作用,所以不正当地使用它 将共享相同的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. 在堆上的被调用函数中分配空间(使用malloccalloc和朋友)并将所有权传递给调用函数,调用函数必须在不需要时释放此空间再使用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只是一个字符串长度(只是一个幻数)