C++ 使用C-string会发出警告:“使用C-string”;与返回的局部变量相关联的堆栈内存地址;

C++ 使用C-string会发出警告:“使用C-string”;与返回的局部变量相关联的堆栈内存地址;,c++,pointers,c-strings,C++,Pointers,C Strings,我不是C程序员,所以我对C-string不太熟悉,但现在我必须使用C库,因此下面是我的代码的一个简短版本,以演示我的问题: char** ReadLineImpl::my_completion () { char* matches[1]; matches[0] = "add"; return matches; } 我收到这样的警告: 警告-返回与局部变量“matches”关联的堆栈内存地址 我的程序似乎不能正常工作(可能是因为上面提到的警告) 这个

我不是C程序员,所以我对C-string不太熟悉,但现在我必须使用C库,因此下面是我的代码的一个简短版本,以演示我的问题:

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

    return matches;
}
我收到这样的警告:

警告-返回与局部变量“matches”关联的堆栈内存地址

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


这个警告意味着什么?它会导致任何问题吗?

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

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

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

  • 匹配项[1]
    声明为
    静态
    静态字符*匹配项[1]-这个
    将在静态空间而不是堆栈上为
    匹配项分配空间(如果您
    不适当地使用它,因为
    my_completion
    函数的所有实例 将共享相同的
    匹配项
    变量)

  • 在调用者函数中分配空间并将其传递给
    my\u completion
    功能:
    myu完成(匹配)

  • 在堆上的被调用函数中分配空间(使用
    malloc
    calloc
    和friends)并将所有权传递给调用方函数,调用方函数在不再需要时必须释放此空间(使用
    free


  • 当您返回
    匹配的
    数组时,您返回的是第一个元素的地址。这存储在
    my\u completion
    内的堆栈中。一旦您从
    my_completion
    返回,内存将被回收,并且(很可能)最终将被重新用于其他用途,覆盖存储在
    匹配项中的值-是的,这可能就是应用程序无法工作的原因-如果不是现在,可能是在您修复了其他一些问题之后,或者稍微改变一下,或者别的什么,因为这不是一个可以安全忽略的小警告

    你可以用几种不同的方法来解决这个问题。最明显的是简单地使用
    std::vector
    [或者更好地使用
    std::vector
    ]:

    std::vector<std::string> ReadLineImpl::my_completion ()
    {
        std::vector<std::string> strings;
        strings.push_back("add");
        return strings;
    }
    
    问题解决了

    变化

    char* matches[1];
    

    使用堆而不是堆栈 对于这种情况,最好使用以下方法在堆中分配内存:

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

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

    您将地址返回到堆栈上分配的第一个字符指针,该指针在退出函数后不再存在。谢谢,我得到了它。最糟糕的是,这是第二次出现这种问题:)无论如何,非常感谢您,因为这是
    GNU readline
    ,这将导致崩溃,因为
    readline
    将释放完成函数返回的内存。@MatsPeterson这看起来像是readline-在这种情况下,您是对的。我将投票表决你的答案!声明<代码>匹配< <代码> >代码>静态将在静态空间上分配空间,而不是堆上。第三选项是通过调用CALROCI分配内存,将使用向量作为C++程序员,但库需要char **,所以我必须转换成char **。所以,假设您使用的是 Realth> 接口,然后必须使用malloc分配内存,因为
    readline
    稍后会释放内存。我会编辑。很好,只有一件事,我必须使用(char**)malloc(1*sizeof(char*)),但是谢谢,你的答案更好,尽管我不会改变为什么?也许,你应该描述一下这样做的原因。
    char* matches[1];
    
    char *matches = new matches[1];
    
    int* someDataForParams(void *_params) {
    
        ...
        int* charCounts = calloc(96, sizeof(char*));
        ...
    
        return charCounts;
    }