为什么会调用这个 dangling-gsl 警告?

问题描述

我正在使用 clang-tidy 分析代码库并看到一个我不明白的警告。警告由以下代码调用

void fun(const QString& bar) {
    const char* c_format = bar.toStdString().c_str();
    expand_some_macro(c_format);
}

c_format 在扩展宏中传递,如下所示:

#define expand_some_macro(c_format)\
    char buffer[MAX_SIZE];\
    va_list args;\
    va_start(args,c_format);\
    vsnprintf(buffer,MAX_SIZE,_TruncATE,c_format,args);\
    va_end(args);

其中包括来自 shlobj 标头的函数调用,我目前不明白。 clang-tidy 生成以下警告:

warning: object backing the pointer will be destroyed at the end of the full-expression [clang-diagnostic-dangling-gsl]

我浏览了网络,特别是 c++ core guidelines,试图让自己了解这个警告,但找不到合适的参考资料。这让我想到了两组问题:

  1. 这个警告的参考是什么?我在哪里可以了解类似的警告?
  2. 上面的代码可能有什么问题?我是否需要在范围末尾调用 delete[] c_format

解决方法

考虑声明...

const char* c_format = bar.toStdString().c_str();

bar.toStdString() 返回一个临时的 std::string,它将在下一个语句之前被销毁。但是您随后针对该临时变量调用 std::string::c_str() 并保存其返回值以用于...

expand_some_macro(c_format);

因此,当 c_format 在上面的表达式中使用时,它指向的内存已经在临时 std::string 被销毁时被释放。因此发出警告。

但是,在不知道您的宏的作用(或为什么它需要成为宏)的情况下,很难说得更多。

编辑:

澄清一下,您当前拥有的代码可以(或多或少)重写为...

const char* c_format = nullptr;
{
    std::string str = bar.toStdString();
    c_format = str.c_str();
}
expand_some_macro(c_format);

所以您使用的内存超出了 c_format 的生命周期。