C++ G++ 错误:[-Werror=数组边界]

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

使用以下命令构建和安装 C++ 项目的二进制文件时:

make install
我收到以下错误:

> Compiling algorithm/fba2-inst6.cpp [qkd_commsys_simulator-omp-mpi-gmp: release]
> In member function ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = bool; _Args = {}; _Tp = bool]’,
> inlined from ‘typename std::enable_if<boost::detail::alloc_has_construct<void, A, T, Args ...>::value>::type boost::allocator_construct(A&, T*, Args&& ...) [with A = std::allocator<bool>; T = bool; Args = {}]’ at /usr/include/boost/core/allocator_access.hpp:432:16,
> inlined from ‘void boost::alloc_construct_n(A&, T*, std::size_t) [with A = std::allocator<bool>; T = bool]’ at /usr/include/boost/core/alloc_construct.hpp:122:35,
> inlined from ‘void boost::multi_array<T, NumDims, Allocator>::allocate_space() [with T = bool; long unsigned int NumDims = 1; Allocator = std::allocator<bool>]’ at /usr/include/boost/multi_array.hpp:548:29,
> inlined from ‘boost::multi_array<T, NumDims, Allocator>::multi_array(const Allocator&) [with T = bool; long unsigned int NumDims = 1; Allocator = std::allocator<bool>]’ at /usr/include/boost/multi_array.hpp:156:19:
> cc1plus: error: ‘void* __builtin_memset(void*, int, long unsigned int)’ offset 0 is out of the bounds [0, 0] [-Werror=array-bounds]
> cc1plus: all warnings being treated as errors
> make[2]: *** [Makefile:75: release/x86_64/qkd_commsys_simulator-omp-mpi-gmp/algorithm/fba2-inst6.o] Error 1
> make[1]: *** [Makefile:407: Libraries/Libcomm] Error 2
make: *** [Makefile:373: install-libs-release] Error 2

如上图具体错误为:

cc1plus: error: ‘void* __builtin_memset(void*, int, long unsigned int)’ offset 0 is out of the bounds [0, 0] [-Werror=array-bounds]

如何消除此错误以使用 g++ 版本 11.4 编译二进制文件?

请注意,这些是我正在使用的以下 Ubuntu 和软件包/依赖项版本:

  • 最新 WSL
  • Ubuntu版本:Ubuntu 22.04.03 LTS
  • G++版本:11.4.0
  • GNU Make 版本:4.3.0
  • 增强版本:1.74
  • C++版本:C++代码最高支持C++17

另请注意,g++编译器无法降级,必须支持11.4版本。

运行 make install 命令时,调试中的所有二进制文件都可以正常工作,直到编译算法/fba2-inst6.cpp 文件为止,所有其他 cpp 文件甚至可以在发布模式下工作。尝试在发布模式下编译此 (algorithm/fba2-inst6.cpp) cpp 文件时,编译停止。

我只能通过将 g++ 编译器降级到版本 10.5 来获得二进制文件的完整编译,但正如我上面所说,使用版本 10.5 是不可接受的,我需要代码来使用 g++ 版本 11.4。

有关

algorithm/fba2-inst6.cpp
文件的完整代码是:

#include "fba2-implementation.h"

// Explicit Realizations
#include "gf.h"
#include "logrealfast.h"
#include "modem/tvb-receiver.h"
#include "mpgnu.h"

namespace libcomm
{

#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/first_n.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/for_each_product.hpp>

using libbase::logrealfast;
using libbase::mpgnu;

// clang-format off
#define USING_GF(r, x, type) \
      using libbase::type;

BOOST_PP_SEQ_FOR_EACH(USING_GF, x, GF_TYPE_SEQ)

#define SYMBOL_TYPE_SEQ \
   (bool) \
   GF_TYPE_SEQ

#define REAL_PAIRS_SEQ \
   ((mpgnu)(mpgnu)) \
   ((logrealfast)(logrealfast)) \
   ((double)(double)) \
   ((double)(float)) \
   ((float)(float))

#define FLAG_SEQ \
   (true)(false)

// *** Instantiations for tvb ***

#define INSTANTIATE3(args) \
      template class fba2<tvb_receiver< \
         BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FIRST_N(3,args))> , \
         BOOST_PP_SEQ_ENUM(args)> ;

#define INSTANTIATE2(r, flags, reals) \
      INSTANTIATE3( (BOOST_PP_SEQ_ELEM(6,SYMBOL_TYPE_SEQ)) reals flags )

#define INSTANTIATE1(r, flags) \
      BOOST_PP_SEQ_FOR_EACH(INSTANTIATE2, flags, REAL_PAIRS_SEQ)
// clang-format on

BOOST_PP_SEQ_FOR_EACH_PRODUCT(INSTANTIATE1, (FLAG_SEQ)(FLAG_SEQ)(FLAG_SEQ))

} // namespace libcomm
c++ boost makefile g++
1个回答
0
投票

您的问题没有包含足够的细节来全面分析您的具体问题;您添加到帖子中的代码片段只是宏的集合,其中一些我们无权访问。

因此,以下只是一些一般性评论:

  • 您使用

    -Werror
    编译代码,这使得 all 编译器警告致命。这可能是因为您正在编译的代码的构建系统会自动执行此操作,这可能是因为您明确设置了该选项。

    一般来说,虽然在开发自己的代码时使用

    -Werror
    使所有警告变得致命可能很有用,但在构建其他人的代码时启用它很少是一个好主意,特别是使用不同的编译器版本 - 特别是因为较新的编译器可能会添加新的警告。

  • 该代码似乎有一个非常间接的

    memset()
    调用,大小为
    0
    。虽然“这是有效的”,但如果指针指向经过边界检查的内存区域的末尾,GCC 11 似乎会生成一个“警告”。与 -Warray-bounds 结合起来,这将成为构建错误,导致构建中止。
    总的来说,我认为编译器在使用零大小参数调用 
    -Werror
    时发出警告是有好处的(因为这可能是错误的指示;但在某些情况下它也可能是合法的),但我相信

    memset()

    是错误的警告类型。

    在你的情况下,这并不重要,因为
    -Warray-bounds
    (没有

    -Werror

    来选择特定警告)会使任何警告致命,无论哪种类型,所以即使GCC正确地发出不同的警告,你的构建还是会失败。

    (请注意,GCC 11.3.0 至少不会在具有正常 
    -Werror=xxx
    的非常简化的测试用例中发出此特定警告,因此编译器认为可以用

    memset

    替换的某些代码可能会触发此错误。)

    
    
    针对您的情况,最好的解决方案是告诉构建系统不要使用 

    memset
  • 来编译您要编译的代码。如果您自己添加了
-Werror

,那么将其删除应该很容易。如果软件的作者直接将其添加到构建系统中,那么这可能会更复杂。由于您没有提到您正在尝试构建哪个软件,以及正在使用哪个构建系统(除了似乎生成

-Werror
的东西之外),因此不可能在这里提供更具体的答案。
    

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