以下代码在GCC 8.0.1下使用或不使用用户定义的复制构造函数的行为有所不同:
#include <cassert>
struct S {
int i;
int *p;
S() : i(0), p(&i) {}
// S(const S &s) : i(s.i), p(&i) {} // #1
// S(const S &s) : i(s.i), p(s.p) {} // #2
// S(const S &s) = delete; // #3
};
S make_S() {return S{};}
int main()
{
S s = make_S();
assert(s.p == &s.i);
}
Run Code Online (Sandbox Code Playgroud)
使用注释的用户定义的复制构造函数(即使是#2,执行简单的浅复制的那个),断言也不会失败,这意味着保证的复制省略按预期工作.
然而,在没有任何用户定义的复制构造,则断言失败,这意味着该对象s在main功能不被缺省构造.为什么会这样?保证复制省略不在这里执行吗?
海湾合作委员会8增加了-Wstringop-truncation警告.来自https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82944:
在GCC 8.0中通过r254630为bug 81117添加的-Wstringop-truncation警告专门用于突出显示strncpy函数的非预期用途,该函数截断源字符串中的终止NUL字符.请求中给出的此类滥用的示例如下:
char buf[2];
void test (const char* str)
{
strncpy (buf, str, strlen (str));
}
Run Code Online (Sandbox Code Playgroud)
我用这段代码得到了同样的警告.
strncpy(this->name, name, 32);
warning: 'char* strncpy(char*, const char*, size_t)' specified bound 32 equals destination size [-Wstringop-truncation`]
Run Code Online (Sandbox Code Playgroud)
考虑到this->name是char name[32]和name是一个char*具有长度可能比32更大我想复制name成this->name和截断它,如果它是大于32更大的应该size_t是31而不是32?我糊涂了.this->nameNUL终止并不是强制性的.
考虑这个简单的程序:
#include <string>
#include <sparsehash/dense_hash_map>
int main()
{
google::dense_hash_map<std::string, int> map;
map["foo"] = 0;
}
Run Code Online (Sandbox Code Playgroud)
使用GCC 8.2和-Wclass-memaccess(或-Wall)进行编译会产生警告:
sparsehash/internal/libc_allocator_with_realloc.h:68:40: warning:
‘void* realloc(void*, size_t)’ moving an object of non-trivially copyable type
‘struct std::pair<const std::__cxx11::basic_string<char>, int>’;
use ‘new’ and ‘delete’ instead [-Wclass-memaccess]
return static_cast<pointer>(realloc(p, n * sizeof(value_type)));
~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
问题是:
我在这里提出了一个问题:https://github.com/sparsehash/sparsehash/issues/149
此 MCVE 使用 gcc 7.3 编译/运行:
请注意,此 MCVE 已显着减少以保持错误重现,因此Allocator模板中的代码没有意义,但不会影响星座!
#include <regex>
#include <string>
#include <iostream>
namespace FaF
{
template <typename T>
class Allocator
{
public:
typedef T value_type;
Allocator() throw() {}
template <typename U> Allocator (const Allocator<U>&) throw() {}
~Allocator() throw() {}
T* allocate (std::size_t num, const void* hint = 0)
{
(void) hint; (void) num;
return new ( T );
}
void deallocate (T* p, std::size_t num) { (void) num; (void) p; }
};
using string = …Run Code Online (Sandbox Code Playgroud) 我想尝试在C ++ 17的新的文件系统库,因此试图复制从cppreference.com的std ::文件系统::例子的current_path并使用最新版本(16.0)编译它MinGW的分布从nuwen.net上我的Windows 10 x64计算机。其中包括gcc v8.1,根据cppreference.com编译器支持页面,该文件应支持文件系统库。
这是我要编译的代码:
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
std::cout << "Current path is " << fs::current_path() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
和我正在使用的编译器命令:
g++ -std=c++17 filesystem_test.cpp
Run Code Online (Sandbox Code Playgroud)
这是我尝试编译时遇到的错误:
In file included from c:\mingw\include\c++\8.1.0\filesystem:37,
from filesystem_test.cpp:2:
c:\mingw\include\c++\8.1.0\bits\fs_path.h: In member function 'std::filesystem::__cxx11::path& std::filesystem::__cxx11::path::operator/=(const std::filesystem::__cxx11::path&)':
c:\mingw\include\c++\8.1.0\bits\fs_path.h:237:47: error: no match for 'operator!=' (operand types are 'std::filesystem::__cxx11::path' and 'std::filesystem::__cxx11::path')
|| (__p.has_root_name() && __p.root_name() != root_name()))
~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~
In file included from c:\mingw\include\c++\8.1.0\iosfwd:40,
from …Run Code Online (Sandbox Code Playgroud) 我正在使用 gcc 8.2.1 并尝试构建此代码:
std::string dir = "Documents";
char * _tempname = static_cast <char*> (malloc( dir.length() + 14));
strncpy (_tempname, dir.c_str(), dir.length()+1 );
strncat (_tempname, "/hellooXXXXXX", 13);
Run Code Online (Sandbox Code Playgroud)
但它给了我这个警告:
警告:
'char* strncat(char*, const char*, size_t)'指定的边界 13 等于源长度 [-Wstringop-overflow=]
搜索后,我发现根据此链接中的讨论,size_t 等于源长度是一个溢出问题,但我不明白为什么这被认为是一个问题以及为什么这会溢出目标。以及如何在不更改代码的情况下删除此警告?
我一直在尝试在新的 Ubuntu 20.04 机器上构建特定版本的 GCC (8.3.0)。但是,当我按照以下链接中的步骤操作时:https://gcc.gnu.org/wiki/InstallingGCC我遇到了 Makefile 错误。
脚步:
wget https://ftp.gnu.org/gnu/gcc/gcc-8.3.0/gcc-8.3.0.tar.xz
tar xf gcc-8.3.0.tar.xz
cd gcc-8.3.0
./contrib/download_prerequisites
cd .. ; mkdir build ; cd build
../gcc-8.3.0/configure --prefix=/opt/gcc-8.3 --enable-languages=c,c++,fortran --disable-multilib
Run Code Online (Sandbox Code Playgroud)
配置输出:
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether ln works... yes
checking whether ln -s works... yes
checking for a sed that does not truncate output... /usr/bin/sed
checking for gawk... no
checking …Run Code Online (Sandbox Code Playgroud) 我正在尝试修复一些 gcc-8 抱怨 Wstringop-truncation 的 C 代码(代码在这里)
\n\n当在我无法控制的服务器上编译该代码时,既不能添加编译指示语句,也不能禁用 Wstringop-truncation 诊断,我收到的警告是:
\n\ngcc-8 -I"/home/hornik/tmp/R/include" -DNDEBUG -I./cqdb/include -I./crf/src -I./liblbfgs/include -I./include -I"/home/hornik/lib/R/Library/3.6/x86_64-linux-gnu/Rcpp/include" -I/usr/local/include -fpic -g -O2 -Wall -pedantic -mtune=native -c cqdb/src/cqdb.c -o cqdb/src/cqdb.o\ncqdb/src/cqdb.c: In function \xe2\x80\x98cqdb_writer_close\xe2\x80\x99:\ncqdb/src/cqdb.c:270:5: warning: \xe2\x80\x98strncpy\xe2\x80\x99 output truncated before terminating nul copying 4 bytes from a string of the same length [-Wstringop-truncation]\n strncpy((char*)header.chunkid, CHUNKID, 4);\n ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ncqdb/src/cqdb.c: In function \xe2\x80\x98cqdb_reader\xe2\x80\x99:\ncqdb/src/cqdb.c:469:9: warning: \xe2\x80\x98strncpy\xe2\x80\x99 specified bound 4 equals destination size [-Wstringop-truncation]\n strncpy((char*)db->header.chunkid, (const char*)p, 4);\n ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nRun Code Online (Sandbox Code Playgroud)\n\n我想重写 strncpy 语句以删除这些警告。我是否正确,我需要替换以下几行
\n\n …我有一个非常简单的代码示例,当-O2在gcc 8.2.0下进行优化时会崩溃
#include <vector>
#include <functional>
#include <iostream>
template<typename T, typename Container>
class Lambda_Expression
{
using Lambda = std::function<T()>;
const Lambda & _lambda;
public:
Lambda_Expression(const Lambda & l) : _lambda(l) {}
T operator[](const std::size_t i)
{
std::cerr << "inside expression [] " << i << std::endl;
return _lambda();
}
};
auto lambda = []() -> double
{
return 1.0;
};
int main()
{
int N = 10;
std::vector<double> res(N, 0.0);
double x = lambda();
std::cerr << "before for …Run Code Online (Sandbox Code Playgroud) 我正在使用 pimpl idiom 和 unique_ptr 编写一些代码。当我尝试使用类内初始化将 unique_ptr 默认设置为 nullptr 时,gcc 给出了编译错误,而 clang 和 msvc 都成功编译了代码。如果我没有使用类内初始化,错误就会消失。
\n\n// A.h\n#pragma once\n\n#include <memory>\n\nusing namespace std;\n\nclass B;\nclass A\n{\nprivate:\n ////////////////////////\n // here gives the error!\n ////////////////////////\n unique_ptr<B> impl{nullptr}; // error only with gcc, \n // ok with clang and msvc\n unique_ptr<B> impl2; // ok with all three\n\npublic:\n A();\n ~A();\n};\nRun Code Online (Sandbox Code Playgroud)\n\n// A.cpp\n#include "A.h"\n\nclass B\n{\nprivate:\n int b{5};\n\npublic:\n B() = default;\n ~B() = default;\n};\n\nA::A() = default;\nA::~A() = default;\nRun Code Online (Sandbox Code Playgroud)\n\n// main.cpp\n#include "A.h"\n\nint main()\n{\n A a;\n return 0;\n}\n …Run Code Online (Sandbox Code Playgroud) gcc8 ×10
c++ ×8
gcc ×5
c++17 ×4
strncpy ×2
build ×1
c ×1
copy-elision ×1
gcc-warning ×1
lambda ×1
makefile ×1
mingw-w64 ×1
pimpl-idiom ×1
realloc ×1
sparsehash ×1
string ×1
unique-ptr ×1
windows-10 ×1