又一个警告:“<anonymous>”可能会在未初始化的情况下使用

问题描述 投票:0回答:1

我看到了许多其他关于同一警告的问题,但我的代码似乎不同。
而且,总的来说,我只能通过 -Os 选项才能得到这个。

#include <iostream>
using namespace std ;

template <class TYPE,class FUNC> struct AutoDestruct
    {
    const TYPE & var ;
    FUNC         func ;
    AutoDestruct ( const TYPE & v , FUNC f ) : var(v),func(f) {}
   ~AutoDestruct ()                          { func(var) ;}
    };

class Dictionary
    {
    public:
        Dictionary & wipe  () { cout << "Dictionary.wipe()\n" ; return *this ;}
    };

static void wipe_dict ( Dictionary * dict ) { dict->wipe() ;}
typedef AutoDestruct<Dictionary*,void(*)(Dictionary*)> AutoWipe ;
    
int main ()
    {
    cout << "enter main function    " << __DATE__ << "  " << __TIME__ << endl ;
    Dictionary headers ;
    AutoWipe   auto_wipe( &headers,wipe_dict ) ;
    cout << "exit main function\n" ;
    }

命令行是:

g++ -std=c++11 -Os -Wall -Wextra test.cpp && ./a.out

N.B.:如果我删除 -Os 选项,我不会收到任何警告。

输出是:

test.cpp: In function ‘int main()’:
test.cpp:9:48: warning: ‘<anonymous>’ may be used uninitialized [-Wmaybe-uninitialized]
    9 |    ~AutoDestruct ()                          { func(var) ;}
      |                                                ^~~~
test.cpp:25:46: note: ‘<anonymous>’ was declared here
   25 |     AutoWipe   auto_wipe( &headers,wipe_dict ) ;
      |                                              ^
enter main function    May 13 2024  20:14:01
exit main function
Dictionary.wipe()

编译器是:

g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0

这是我真实代码的一个非常简单的摘录,只是为了暴露警告。
但请注意,在我的真实代码中,执行 auto_wipe 时,我收到警告 AND 段错误!

知道警告+段错误原因吗? 预先感谢!

c++ g++ gcc-warning
1个回答
0
投票

我认为走一小段路是值得的,因为我想我不是唯一一个最初误读你的代码的人。我认为我正在阅读的代码是这样的:

#include <iostream>
using namespace std;

template <class TYPE,class FUNC> struct AutoDestruct {
    TYPE& var ;
    FUNC func ;
    AutoDestruct(TYPE& v, FUNC f ) : var(v),func(f) {}
    ~AutoDestruct () { func(var) ;}
};

struct Dictionary {
    Dictionary & wipe  () { cout << "Dictionary.wipe()\n" ; return *this ;}
};

static void wipe_dict ( Dictionary & dict ) { dict.wipe() ;}
typedef AutoDestruct<Dictionary,void(*)(Dictionary&)> AutoWipe ;
    
int main () {
    Dictionary headers ;
    AutoWipe auto_wipe( headers,wipe_dict) ;
}

auto_wipe
存储对
headers
的引用,当调用它的析构函数时,它会调用
headers.wipe();
。然后调用
headers
析构函数,一切都很好。

虽然在你的代码中,这里:

AutoWipe   auto_wipe( &headers,wipe_dict ) ;

您的

auto_wipe
存储对临时
&headers
的引用。当
auto_wipe
的析构函数被调用时,对象
headers
当然仍然存储在相同的内存地址中。然而,由
&headers
产生的临时指针早已消失,并且该成员是一个悬空引用。您可以按照注释中的建议复制指针,也可以按照上面的方式存储对实际对象的引用。

TL;DR:编译器发出警告是正确的。您存储一个悬空引用。使用地址消毒剂会突出这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.