使用 C 字符串会发出警告:"Address of stack memory associated with local variable returned"



我不是C程序员,所以我对C字符串不太熟悉,但现在我必须使用C库,所以这里是我的代码的缩短版本来演示我的问题:

char** ReadLineImpl::my_completion () {
    char* matches[1];
    matches[0] = "add";
    return matches;
}

我收到这个警告:

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

我的程序似乎无法正常工作(可能是因为上面提到的警告)。

这个警告意味着什么?它会引起什么问题吗?

变量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;
    }
    
  3. 在堆上的被调用函数中分配空间(使用malloccalloc和friends),并将所有权传递给调用方函数,调用方函数在不再需要时必须释放此空间(使用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;
}

因此,如果库根据readline接口需要char **,则使用以下内容:

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

问题解决了!

使用堆而不是堆栈

最好在堆上为分配内存,这种情况下使用:

int* someDataForParams(void *_params) {
    // ...
    int* charCounts = (int*) calloc(96, sizeof(char*));
    // ...
    return charCounts;
}

96只是一个字符串长度(只是一个幻数)。

有两种解决方案:

第一种方法是使用关键字static将变量声明为静态变量。

第二种解决方案是与malloccalloc一起使用动态分配。

最新更新