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

kha*_*vah 23 c++ pointers c-strings

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

char** ReadLineImpl::my_completion () {

    char* matches[1];


    matches[0] = "add";

    return matches;

}
Run Code Online (Sandbox Code Playgroud)

我收到警告:

警告 - 与返回的本地变量"matches"关联的堆栈内存的地址

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

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

Nem*_*ric 36

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

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

您可以通过多种方式解决此问题,其中一些方法是:

  1. 声明matches[1]static:static 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;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在堆上的被调用函数中分配空间(使用malloc,calloc和朋友),并将所有权传递给调用者函数,调用函数将不再需要时(释放)释放此空间free.

  • 将`matches`声明为`static`将在静态空间上分配空间,而不是在堆上. (4认同)
  • 第三个选项是通过调用calloc在堆中分配内存 (2认同)

Mat*_*son 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;
}
Run Code Online (Sandbox Code Playgroud)

编辑:那么,如果库需要一个char **readline接口,那么使用这个:

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

问题解决了!