G++ :检测到std后使用::移动

发布于 2025-02-05 03:55:24 字数 456 浏览 2 评论 0原文

由于使用了std :: vector,我刚刚在代码中发现了一个错误。该代码类似于:

std::vector<SomeObject> v1;
//fill v1;
this->v2=std::move(v1);
for(unsigned int i=0; i<v1.size(); i++)
{
    //the code in the for loop was not executed
}

行为不足为奇(V1的状态是未定义的,只要有效;因此空置向量似乎是合乎逻辑的选择)。

我的问题是:在移动变量后使用变量时,是否有可能让我警告我?如果是这样,我应该添加哪个标志?

NB:我认为无法确保检测到这种警告(我认为这等同于停止问题,这是无法解决的)。但是,如果我在示例(例如,可以证明又一次使用后使用)警告,或者如果G ++无法证明它是安全的,那将非常有用。

非常感谢

I just found an error in my code due to using an std::vector after having moved it. The code was something like :

std::vector<SomeObject> v1;
//fill v1;
this->v2=std::move(v1);
for(unsigned int i=0; i<v1.size(); i++)
{
    //the code in the for loop was not executed
}

The behavior is not surprising (the state of v1 is undefined, as long as it is valid; so an empty vector seems a logical choice).

My question is : is it possible to make g++ give me a warning when using a variable after moving it? If so, what flag should I add?

NB : I suppose it is not possible to guarantee the detection of such warning (it would, I think, be equivalent to the halting problem, that can't be solved for the general case). But it would already be very useful if I get a warning either for simple cases like the example (use after move can be proven), or if I get a warning when g++ can't prove that it is safe.

Thanks a lot in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

财迷小姐 2025-02-12 03:55:24

我认为GCC对此没有诊断。

但是,Clang静态分析仪和Clang-Tidy做到了。如果您在此类代码上运行它们(两者),并启用了所有诊断,则获得(摘录):

<source>:7:34: warning: 'v1' used after it was moved [bugprone-use-after-move,hicpp-invalid-access-moved]
    for (unsigned int i = 0; i < v1.size(); i++) {
                                 ^
<source>:6:15: note: move occurred here
    auto v2 = std::move(v1);

/*...*/

<source>:7:34: warning: Method called on moved-from object 'v1' of type 'std::vector' [clang-analyzer-cplusplus.Move]
    for (unsigned int i = 0; i < v1.size(); i++) {
                                 ^~~~~~~~~
<source>:6:15: note: Object 'v1' of type 'std::vector' is left in a valid but unspecified state after move
    auto v2 = std::move(v1);
              ^~~~~~~~~~~~~
<source>:7:34: note: Method called on moved-from object 'v1' of type 'std::vector'
    for (unsigned int i = 0; i < v1.size(); i++) {
                                 ^~~~~~~~~

请参阅

其他衬里和静态分析仪可能已经实施了类似的诊断。 GCC现在还具有静态分析仪(使用-Fanalyzer启用),但似乎还没有实现的诊断。


但是,此类诊断可能很容易是错误的阳性(这可能是编译器不作为直接编译器警告实施它们的原因)。

例如,std :: simolor_ptr从移动时具有非常清晰的行为。最终的状态是一个空的std :: simolor_ptr。如果是稍后检查是否为空,则没有问题。

同样,搬迁后可以重复使用所有行为良好类型的对象。移动后立即可以简单地指定。但是例如,分配新状态应该很好。

I don't think GCC has a diagnostic for that.

However the Clang static analyzer and Clang-tidy do. If you run them (both) on such code with all diagnostics enabled you get (excerpt):

<source>:7:34: warning: 'v1' used after it was moved [bugprone-use-after-move,hicpp-invalid-access-moved]
    for (unsigned int i = 0; i < v1.size(); i++) {
                                 ^
<source>:6:15: note: move occurred here
    auto v2 = std::move(v1);

/*...*/

<source>:7:34: warning: Method called on moved-from object 'v1' of type 'std::vector' [clang-analyzer-cplusplus.Move]
    for (unsigned int i = 0; i < v1.size(); i++) {
                                 ^~~~~~~~~
<source>:6:15: note: Object 'v1' of type 'std::vector' is left in a valid but unspecified state after move
    auto v2 = std::move(v1);
              ^~~~~~~~~~~~~
<source>:7:34: note: Method called on moved-from object 'v1' of type 'std::vector'
    for (unsigned int i = 0; i < v1.size(); i++) {
                                 ^~~~~~~~~

See godbolt. The first being the clang-tidy diagnostic and the second being the static analyzer diagnostic.

Other linters and static analyzers probably have similar diagnostics implemented. GCC also now has a static analyzer (enabled with -fanalyzer), but it doesn't seem to have a diagnostic for this implemented yet.


Such diagnostics may however easily be false-positives (which may be a reason that the compilers don't implement them as direct compiler warnings).

For example std::unique_ptr has a very clear behavior when moved from. The resulting state is that of an empty std::unique_ptr. If it is then later checked for whether it is empty or not, there is no issue.

Also, objects of all well-behaved types can be reused after a move. The state immediately after the move may simply be unspecified. But e.g. assigning a new state should be fine.

早茶月光 2025-02-12 03:55:24

我认为这不可能。移动语义并未指定已移动的对象的状态。这取决于实施。

例如,对向量分配的移动分配非常合理的实现是在两个向量之间交换数据。因此,在您的代码中,v1.size()将是移动分配之前的v2的大小。谁说班级没有指定语义?使用后使用是完全合理的。

显然,在STL中,移动构造函数使移动的容器空移动。但这仍然具有完全有效的v1.size()0

每个移动的对象都有一些有效使用的方法。至少应始终允许分配。对于STL容器,我希望大小()在所有情况下也有效,但也许不会返回您的期望。但是,编译器应该如何知道哪些方法可以保存在移动对象上?

为了使编译器发出感官警告,我认为编译器(或C ++)需要引入一些新属性,并且STL需要注释它的移动构造函数 /移动分配。这样,编译器可以知道移动构造函数 /分配是否遵循有效但未指定状态的某个语义< / em>。

I do not believe this is possible in general. The move semantic does not specify the state of an object that was moved from. That depends on the implementation.

For example a very reasonable implementation for the move assignment of vector is to swap the data between the two vectors. So in you code example the v1.size() would be the size of v2 from before the move assignment. Who is to say the class does not specify that semantic? It would be perfectly reasonable to use-after-move.

Apparently in the STL the move constructor leaves the moved from container empty. But that would still have a perfectly valid v1.size()of 0.

Every moved-from object has some methods that are valid to use. At a minimum assignment should always be allowed. For STL containers I expect size() to also be valid in all cases but maybe not return what you expect. But really how is the compiler supposed to know which methods are save to call on moved-from objects?

For the compiler to give sensical warnings I think the compiler (or C++) needs to introduce some new attributes and the STL needs to annotate it's move constructors / move assignment. That way the compiler could know if a move constructor / assignment follows a certain semantic beyond valid but unspecified state.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文