检测全局变量的移动后使用

alf*_*lfC 8 c++ static-analysis move clang clang-tidy

经过一番努力,我说服 clang 编译器和 clang-tidy(静态分析器)对移动后使用的情况发出警告。(参见/sf/answers/5197539721/

int main(int, char**) {
    a_class a;
    auto b = std::move(a);
    a.f();  // warns here, for example "invalid invocation of method 'f' on object 'a' while it is in the 'consumed' state [-Werror,-Wconsumed]"
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我将变量设置为全局变量(或静态或惰性静态),则不再有警告。

a_class a;

int main(int, char**) {
    auto b = std::move(a);
    a.f();  // no warns here!
}
Run Code Online (Sandbox Code Playgroud)

请参阅此处: https: //godbolt.org/z/3zW61qYfY

是否可以在编译时对全局变量进行某种类型的移动后使用检测?或者即使在原则上也是不可能的?


注意:请不要讨论全局对象(我知道这是一个坏主意)或使用移动对象的合法性(我知道有些类是为此设计的)。这个问题是技术性的,涉及用于检测程序中某种容易出现错误的模式的编译器和工具。


完整的工作代码,clang ... -Wconsumed -Werror -std=c++11使用clang-tidy. clang 注释(扩展)帮助编译器检测模式。

#include<cassert>
#include<memory>

class [[clang::consumable(unconsumed)]] a_class {
    std::unique_ptr<int> p_;

public:
    [[clang::callable_when(unconsumed)]]
    void f() {}

    // private: [[clang::set_typestate(consumed)]] void invalidate() {}  // not needed but good to know
};

a_class a;

int main(int, char**) {
    // a_class a;
    auto b = std::move(a);
    a.f();  // global doesn't warn here
}
Run Code Online (Sandbox Code Playgroud)

我能找到的关于这个 clang 扩展的大部分信息都来自这里:Andrea Kling 的博客https://awesomekling.github.io/Catching-use-after-move-bugs-with-Clang-consumed-annotations/

J. *_*old 0

您可以将cppcheckperformancestyle检查一起使用。与cppcheck --enable=performance,style file.cpp您可以检查您的file.

例如,在以下代码中(简单的移动后使用):

#include <utility>

// Declare a global variable
int globalVariable = 0;

int main() {
  // Move the global variable to a local variable
  int localVariable = std::move(globalVariable);

  // Access the global variable after it has been moved
  return globalVariable;
}

Run Code Online (Sandbox Code Playgroud)

它会产生[my_file.cpp:8]: (performance) Access to moved-from object 'globalVariable'.并因此检测移动后使用的情况!:)