Cppcheck警告初始化列表中指向局部变量的指针。

6
我使用cppcheck分析了一些代码,以查找错误和代码质量。我遇到了一个错误,我认为这是一个误报。以下代码示例显示了问题(用注释标记)。
cppcheck - v 1.89
#include <string>
#include <vector>
#include <iostream>

std::string func() {
    std::vector<char> data{};
    data.push_back('a');
    data.push_back('b');
    data.push_back('c');
    return std::string{ data.data(), data.size() }; // error marked here
    // severity: error
    // line: 12
    // summary: Returning object that points to local variable 'data' that will be invalid when returning.
}

int main() {
    std::string ret{};
    {
        ret = func();
    }
    std::cout << ret << std::endl;
    return 0;
}

如果我使用括号 () 而不是花括号 {},就可以解决错误。
编辑:
当我使用 (){} 调试示例时,完全没有区别。 我使用带有C++14的Visual Studio 17。

你的代码行std::string将调用字符串类的构造函数,它需要()因为这是一个函数调用。{}用于数据初始化和作用域。 - SPlatten
1
Cppcheck多年来一直存在问题。@SPlatten它是调用构造函数的直接列表初始化语法。 - user7860670
4
如果{}中的内容可以解释为std::initializer_list<char>,那么你会遇到问题(这个问题可以通过使用()``来解决)。否则,使用{}是可以的。当不确定该使用哪种方式时(对于具有std::initializer_list构造函数的类),通常最安全的方法是坚持使用()``。参考例子:这个答案 - Sander De Dycker
1
我怀疑cppcheck只是“玩得保险”。 - Sander De Dycker
正如答案所示,这确实是一个误报。在错误跟踪器中有一个相应的工单,并且已经通过此提交进行了修复。因此,Cppcheck 1.90将不再出现这种误报。 - versat
显示剩余3条评论
2个回答

4

我认为这个规则是针对C++11之前的:

{/*..*/}只能在C++11之前用于聚合初始化,因此T{ data.data(), data.size() }只能存储未来的悬空指针,从而导致诊断。

使用T(data.data(), data.size() )是一个常规的构造函数调用,因此它实际上取决于T的构造函数,因此没有检查T的构造函数就不能安全地进行诊断(并且我怀疑cppcheck是否会检查)(顺便说一下,对于std::string是安全的)。

因此,确实是一个虚假的阳性结果。


2

这是一个误报,因为字符串构造函数会复制传递的char*字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接