警告:对未分配的对象调用了删除操作符

Ale*_*ejo 15 c++ delete-operator c++17 c++20

我正在尝试编译以下代码(这是一个最小的示例),但我收到一条我无法弄清楚的警告:

\n
#include <string>\n#include <variant>\n#include <vector>\n\nstruct Bar {\n  std::wstring x = L"";\n}; \n\nBar Foo() {\n  std::variant<std::vector<int>, Bar> tmp = Bar();\n  if (std::holds_alternative<Bar>(tmp)) return std::move(std::get<Bar>(tmp));\n  return Bar();\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我正在尝试构建这个g++ -std=c++20 -Wall -Wextra -O2 /tmp/test.cc -c

\n

我收到以下警告:

\n
In file included from /usr/include/x86_64-linux-gnu/c++/12/bits/c++allocator.h:33,\n                 from /usr/include/c++/12/bits/allocator.h:46,\n                 from /usr/include/c++/12/string:41,\n                 from /tmp/test.cc:1:\nIn member function \xe2\x80\x98void std::__new_allocator<_Tp>::deallocate(_Tp*, size_type) [with _Tp = int]\xe2\x80\x99,\n    inlined from \xe2\x80\x98constexpr void std::allocator< <template-parameter-1-1> >::deallocate(_Tp*, std::size_t) [with _Tp = int]\xe2\x80\x99 at /usr/include/c++/12/bits/allocator.h:200:35,\n    inlined from \xe2\x80\x98static constexpr void std::allocator_traits<std::allocator<_CharT> >::deallocate(allocator_type&, pointer, size_type) [with _Tp = int]\xe2\x80\x99 at /usr/include/c++/12/bits/alloc_traits.h:496:23,\n    inlined from \xe2\x80\x98constexpr void std::_Vector_base<_Tp, _Alloc>::_M_deallocate(pointer, std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]\xe2\x80\x99 at /usr/include/c++/12/bits/stl_vector.h:387:19,\n    inlined from \xe2\x80\x98constexpr std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = int; _Alloc = std::allocator<int>]\xe2\x80\x99 at /usr/include/c++/12/bits/stl_vector.h:366:15,\n    inlined from \xe2\x80\x98constexpr std::vector<_Tp, _Alloc>::~vector() [with _Tp = int; _Alloc = std::allocator<int>]\xe2\x80\x99 at /usr/include/c++/12/bits/stl_vector.h:733:7,\n    inlined from \xe2\x80\x98constexpr void std::destroy_at(_Tp*) [with _Tp = vector<int>]\xe2\x80\x99 at /usr/include/c++/12/bits/stl_construct.h:88:18,\n    inlined from \xe2\x80\x98constexpr void std::_Destroy(_Tp*) [with _Tp = vector<int>]\xe2\x80\x99 at /usr/include/c++/12/bits/stl_construct.h:149:22,\n    inlined from \xe2\x80\x98std::__detail::__variant::_Variant_storage<false, std::vector<int, std::allocator<int> >, Bar>::_M_reset()::<lambda(auto:11&&)> mutable [with auto:11 = std::vector<int>&]\xe2\x80\x99 at /usr/include/c++/12/variant:472:19,\n    inlined from \xe2\x80\x98constexpr _Res std::__invoke_impl(__invoke_other, _Fn&&, _Args&& ...) [with _Res = void; _Fn = __detail::__variant::_Variant_storage<false, vector<int, allocator<int> >, Bar>::_M_reset()::<lambda(auto:11&&)>; _Args = {vector<int, allocator<int> >&}]\xe2\x80\x99 at /usr/include/c++/12/bits/invoke.h:61:36,\n    inlined from \xe2\x80\x98constexpr std::enable_if_t<is_invocable_r_v<_Res, _Callable, _Args ...>, _Res> std::__invoke_r(_Callable&&, _Args&& ...) [with _Res = void; _Callable = __detail::__variant::_Variant_storage<false, vector<int, allocator<int> >, Bar>::_M_reset()::<lambda(auto:11&&)>; _Args = {vector<int, allocator<int> >&}]\xe2\x80\x99 at /usr/include/c++/12/bits/invoke.h:111:28,\n    inlined from \xe2\x80\x98static constexpr decltype(auto) std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::integer_sequence<long unsigned int, __indices ...> >::__visit_invoke(_Visitor&&, _Variants ...) [with _Result_type = void; _Visitor = std::__detail::__variant::_Variant_storage<false, std::vector<int, std::allocator<int> >, Bar>::_M_reset()::<lambda(auto:11&&)>&&; _Variants = {std::variant<std::vector<int, std::allocator<int> >, Bar>&}; long unsigned int ...__indices = {0}]\xe2\x80\x99 at /usr/include/c++/12/variant:1035:40,\n    inlined from \xe2\x80\x98constexpr decltype(auto) std::__do_visit(_Visitor&&, _Variants&& ...) [with _Result_type = void; _Visitor = __detail::__variant::_Variant_storage<false, vector<int, allocator<int> >, Bar>::_M_reset()::<lambda(auto:11&&)>; _Variants = {variant<vector<int, allocator<int> >, Bar>&}]\xe2\x80\x99 at /usr/include/c++/12/variant:1783:5,\n    inlined from \xe2\x80\x98constexpr void std::__detail::__variant::_Variant_storage<false, _Types ...>::_M_reset() [with _Types = {std::vector<int, std::allocator<int> >, Bar}]\xe2\x80\x99 at /usr/include/c++/12/variant:470:23,\n    inlined from \xe2\x80\x98constexpr std::__detail::__variant::_Variant_storage<false, _Types ...>::~_Variant_storage() [with _Types = {std::vector<int, std::allocator<int> >, Bar}]\xe2\x80\x99 at /usr/include/c++/12/variant:480:17,\n    inlined from \xe2\x80\x98constexpr std::__detail::__variant::_Copy_ctor_base<false, std::vector<int, std::allocator<int> >, Bar>::~_Copy_ctor_base()\xe2\x80\x99 at /usr/include/c++/12/variant:554:12,\n    inlined from \xe2\x80\x98constexpr std::__detail::__variant::_Move_ctor_base<false, std::vector<int, std::allocator<int> >, Bar>::~_Move_ctor_base()\xe2\x80\x99 at /usr/include/c++/12/variant:591:12,\n    inlined from \xe2\x80\x98constexpr std::__detail::__variant::_Copy_assign_base<false, std::vector<int, std::allocator<int> >, Bar>::~_Copy_assign_base()\xe2\x80\x99 at /usr/include/c++/12/variant:629:12,\n    inlined from \xe2\x80\x98constexpr std::__detail::__variant::_Move_assign_base<false, std::vector<int, std::allocator<int> >, Bar>::~_Move_assign_base()\xe2\x80\x99 at /usr/include/c++/12/variant:681:12,\n    inlined from \xe2\x80\x98constexpr std::__detail::__variant::_Variant_base<std::vector<int, std::allocator<int> >, Bar>::~_Variant_base()\xe2\x80\x99 at /usr/include/c++/12/variant:735:12,\n    inlined from \xe2\x80\x98constexpr std::variant<_Types>::~variant() [with _Types = {std::vector<int, std::allocator<int> >, Bar}]\xe2\x80\x99 at /usr/include/c++/12/variant:1407:28,\n    inlined from \xe2\x80\x98Bar Foo()\xe2\x80\x99 at /tmp/test.cc:13:1:\n/usr/include/c++/12/bits/new_allocator.h:158:33: warning: \xe2\x80\x98void operator delete(void*, std::size_t)\xe2\x80\x99 called on unallocated object \xe2\x80\x98tmp\xe2\x80\x99 [-Wfree-nonheap-object]\n  158 |         _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));\n      |                                 ^\n/tmp/test.cc: In function \xe2\x80\x98Bar Foo()\xe2\x80\x99:\n/tmp/test.cc:10:39: note: declared here\n   10 |   std::variant<std::vector<int>, Bar> tmp = Bar();\n      |                                       ^~~\n
Run Code Online (Sandbox Code Playgroud)\n

g++ --versiong++ (Debian 12.2.0-10) 12.2.0

\n

我知道这段代码本身没有多大意义;但它也不应该有这个问题:这是一个展示此警告的最小示例,其功能要复杂得多。

\n

奇怪的是,如果我执行以下任一操作,警告就会消失:

\n
    \n
  1. 更改Bar::xstd::string.
  2. \n
  3. 更改tmp为 be std::variant<int, Bar>(而不是将 astd::vector<int>作为第一种类型)。
  4. \n
  5. 删除 g++ 命令行标志-O2(即使用 进行编译g++ -std=c++20 -Wall -Wextra -O2 /tmp/test.cc -c)。
  6. \n
\n

为什么这些更改会使警告消失!?

\n

如果我用 构建这个--std=c++17,问题仍然存在。

\n

康桓瑋*_*康桓瑋 10

gcc的flag-Wfree-nonheap-object存在一系列误报bug,其中bug 99098就是用来记录这些元bug的。

您的示例中的错误与错误 108088类似并已列出,该错误自 gcc-12 起发出误报警告消息。