相关疑难解决方法(0)

C++标准是否允许未初始化的bool使程序崩溃?

我知道C++ 中的"未定义行为"几乎可以让编译器做任何想做的事情.但是,我遇到了让我感到惊讶的崩溃,因为我认为代码足够安全.

在这种情况下,真正的问题仅发生在使用特定编译器的特定平台上,并且仅在启用了优化时才发生.

我尝试了几件事来重现问题并将其简化到最大程度.这是一个名为的函数的摘录Serialize,它将获取bool参数,并将字符串true或复制false到现有的目标缓冲区.

如果bool参数是未初始化的值,那么这个函数是否会在代码审查中,没有办法告诉它实际上可能会崩溃?

// Zero-filled global buffer of 16 characters
char destBuffer[16];

void Serialize(bool boolValue) {
    // Determine which string to print based on boolValue
    const char* whichString = boolValue ? "true" : "false";

    // Compute the length of the string we selected
    const size_t len = strlen(whichString);

    // Copy string into destination buffer, which is zero-filled (thus already null-terminated)
    memcpy(destBuffer, whichString, len);
}
Run Code Online (Sandbox Code Playgroud)

如果使用clang 5.0.0 +优化执行此代码,它将/可能崩溃.

boolValue ? "true" …

c++ abi llvm undefined-behavior llvm-codegen

482
推荐指数
5
解决办法
3万
查看次数

在内存中我的变量存储在C中?

通过考虑将内存分为四个部分:数据,堆,堆栈和代码,全局变量,静态变量,常量数据类型,局部变量(在函数中定义和声明),变量(在main函数中),指针,并动态分配空间(使用malloc和calloc)存储在内存中?

我认为他们将分配如下:

  • 全局变量------->数据
  • 静态变量------->数据
  • 常量数据类型----->代码
  • 局部变量(在函数中声明和定义)--------> stack
  • 在main函数-----> heap中声明和定义的变量
  • 指针(例如char *arr,int *arr)------->堆
  • 动态分配空间(使用malloc和calloc)-------->堆栈

我只是从C的角度来指这些变量.

如果我错了,请纠正我,因为我是C的新手.

c memory types memory-management

134
推荐指数
5
解决办法
20万
查看次数

为什么std :: optional <int>的构造比std :: pair <int,bool>更昂贵?

考虑这两种可以代表"可选int"的方法:

using std_optional_int = std::optional<int>;
using my_optional_int = std::pair<int, bool>;
Run Code Online (Sandbox Code Playgroud)

鉴于这两个功能......

auto get_std_optional_int() -> std_optional_int 
{
    return {42};
}

auto get_my_optional() -> my_optional_int 
{
    return {42, true};
}
Run Code Online (Sandbox Code Playgroud)

... g ++ trunkclang ++ trunk (with -std=c++17 -Ofast -fno-exceptions -fno-rtti)产生以下程序集:

get_std_optional_int():
        mov     rax, rdi
        mov     DWORD PTR [rdi], 42
        mov     BYTE PTR [rdi+4], 1
        ret

get_my_optional():
        movabs  rax, 4294967338 // == 0x 0000 0001 0000 002a
        ret
Run Code Online (Sandbox Code Playgroud)

godbolt.org上的实例


为什么get_std_optional_int()需要三个mov指令,而get_my_optional()只需要一个 …

c++ performance assembly x86-64 c++17

65
推荐指数
3
解决办法
3365
查看次数

编译器可以从堆优化到堆栈分配吗?

就编译器优化而言,将堆分配更改为堆栈分配是否合法和/或可能?或者会破坏as-if规则

例如,假设这是代码的原始版本

{
    Foo* f = new Foo();
    f->do_something();
    delete f;
}
Run Code Online (Sandbox Code Playgroud)

编译器是否能够将此更改为以下内容

{
    Foo f{};
    f.do_something();
}
Run Code Online (Sandbox Code Playgroud)

我不这么认为,因为如果原始版本依赖于自定义分配器之类的东西,那将会产生影响.标准是否对此有具体说明?

c++ memory-management compiler-optimization language-lawyer

63
推荐指数
2
解决办法
3085
查看次数

为什么C++优化器有这些临时变量的问题,或者为什么在紧密循环中应该避免使用`v []`?

在这段代码中,我正在比较两个功能相同的循环的性能:

for (int i = 1; i < v.size()-1; ++i) {
  int a = v[i-1];
  int b = v[i];
  int c = v[i+1];

  if (a < b  &&  b < c)
    ++n;
}
Run Code Online (Sandbox Code Playgroud)

for (int i = 1; i < v.size()-1; ++i) 
  if (v[i-1] < v[i]  &&  v[i] < v[i+1])
    ++n;
Run Code Online (Sandbox Code Playgroud)

在优化标志设置为O2:的许多不同C++编译器中,第一个运行速度明显慢于第二个编译器:

  • 使用Clang 3.7.0,第二个循环现在了约330%
  • 使用gcc 4.9.3,第二次循环慢约2%
  • 使用Visual C++ 2015,第二个循环慢约2%

我很困惑,现代C++优化器在处理这种情况时遇到了问题.任何线索为什么?我是否必须编写丑陋的代码而不使用临时变量才能获得最佳性能?

现在,使用临时变量可以使代码更快,有时甚至更快.到底是怎么回事?

我正在使用的完整代码如下:

#include <algorithm>
#include <chrono>
#include <random>
#include <iomanip>
#include <iostream>
#include …
Run Code Online (Sandbox Code Playgroud)

c++ optimization performance

61
推荐指数
3
解决办法
5437
查看次数

if(A | B) 总是比 if(A || B) 快吗?

我正在读Fedor Pikus 的这本书,他有一些非常非常有趣的例子,对我来说是一个惊喜。
特别是这个基准测试吸引了我,唯一的区别是在其中一个我们使用 || 在 if 和另一个中我们使用 |。

void BM_misspredict(benchmark::State& state)
{

    std::srand(1);
    const unsigned int N = 10000;;
    std::vector<unsigned long> v1(N), v2(N);
    std::vector<int> c1(N), c2(N);

    for (int i = 0; i < N; ++i) 
    {
        v1[i] = rand();
        v2[i] = rand();
        c1[i] = rand() & 0x1;
        c2[i] = !c1[i];
    }

    unsigned long* p1 = v1.data();
    unsigned long* p2 = v2.data();
    int* b1 = c1.data();
    int* b2 = c2.data();

    for (auto _ : state)
    {
        unsigned long a1 …
Run Code Online (Sandbox Code Playgroud)

c++ optimization benchmarking branch-prediction

55
推荐指数
5
解决办法
1万
查看次数

了解该规则,即“程序已按编写的方式执行”

我正在尝试理解常规规则。根据cppreference

as-if规则
允许进行任何和所有不改变程序可观察行为的代码转换

解释
只要满足以下条件,C ++编译器就可以对程序进行任何更改:[...]

我很难理解“说明”部分的第二个技巧:

2)在程序终止时,写入文件的数据与在执行程序时完全一样。

我只是不明白“程序是按书面形式执行”的意思。

c++ compiler-optimization

53
推荐指数
2
解决办法
2897
查看次数

对于{A = a; B = B; ,"A = a"会在"B = b"之前严格执行吗?

假设A,B,a,和b都是变量,的地址A,B,a,和b都是不同的.然后,对于以下代码:

A = a;
B = b;
Run Code Online (Sandbox Code Playgroud)

C和C++标准是否明确要求A=a在之前严格执行B=b?考虑到的地址A,B,a,和b都不同,编译器允许交换两个语句的执行顺序为某种目的,如优化?

如果我的问题的答案在C和C++中有所不同,我想知道两者.

编辑:问题的背景如下.在棋盘游戏AI设计中,对于优化,人们使用无锁共享哈希表,如果我们不添加volatile限制,其正确性很大程度上取决于执行顺序.

c c++ compiler-construction optimization standards

51
推荐指数
2
解决办法
3672
查看次数

我应该将std :: string与“ string”或“ string” s比较吗?

考虑以下代码片段:

bool foo(const std::string& s) {
    return s == "hello"; // comparing against a const char* literal
}

bool bar(const std::string& s) {
    return s == "hello"s; // comparing against a std::string literal
}
Run Code Online (Sandbox Code Playgroud)

乍一看,它看起来像比对并const char*需要更少的组装说明1,作为使用字符串字面量会导致就地建设std::string

编辑:正如答案中指出的那样,我忘记了有效地s.compare(const char*)将被调用的事实foo(),因此在这种情况下当然不会进行就地构建。因此,请在下面删除一些行。

但是,请operator==(const char*, const std::string&)参阅参考资料:

所有比较都是通过compare()成员函数完成的。

根据我的理解,这意味着我们将需要构造一个结构std::string来执行比较,因此我怀疑最终的开销将是相同的(尽管对的调用已将其隐藏了operator==)。

  • 我应该选择哪个比较?
  • 一个版本是否比另一个版本具有优势(可能在特定情况下)?

1我知道更少的汇编指令并不一定意味着更快的代码,但是我不想在这里进行微基准测试。

c++ string-comparison string-literals c++14 c++17

44
推荐指数
3
解决办法
2894
查看次数

C++在空类中编写和调用的函数是什么?

Effective C++一书中,我看到了以下段落:

结果,如果你写

class Empty{};
Run Code Online (Sandbox Code Playgroud)

它基本上和你写的一样:

class Empty {
public:
    Empty() { ... }
    Empty(const Empty& rhs) { ... }
    ~Empty() { ... }
    Empty& operator=(const Empty& rhs) { ... } // copy assignment operator
};
Run Code Online (Sandbox Code Playgroud)

以下代码将导致生成每个函数:

Empty e1;
Empty e2(e1);
e2 = e1;
Run Code Online (Sandbox Code Playgroud)

但是在拆解通过编译上面的代码创建的可执行文件之后,我意识到并非如此:没有任何函数被调用.

这是主要的汇编代码:

00000000004006cd <main>:
  4006cd:       55                      push   %rbp
  4006ce:       48 89 e5                mov    %rsp,%rbp
  4006d1:       b8 00 00 00 00          mov    $0x0,%eax
  4006d6:       5d                      pop    %rbp
  4006d7:       c3                      retq 
Run Code Online (Sandbox Code Playgroud)

段中没有任何名为"Empty"的函数.text.

那么在我们调用构造函数或赋值空类之后,编译器的行为究竟是什么?这本书说它会产生一些功能吗?如果是这样,他们存放在哪里?

c++ default-constructor effective-c++ empty-class

43
推荐指数
3
解决办法
3287
查看次数