小编coo*_*451的帖子

"volatile"这个定义是不稳定的,还是GCC有一些标准的合规性问题?

我需要一个函数(就像来自WinAPI的SecureZeroMemory)总是将内存归零并且不会被优化掉,即使编译器认为在此之后永远不会再访问内存.似乎是挥发性的完美候选者.但是我实际上遇到了一些与GCC合作的问题.这是一个示例函数:

void volatileZeroMemory(volatile void* ptr, unsigned long long size)
{
    volatile unsigned char* bytePtr = (volatile unsigned char*)ptr;

    while (size--)
    {
        *bytePtr++ = 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

很简单.但是,如果你调用它,GCC实际生成的代码会因编译器版本和你实际尝试为零的字节数而有很大不同.https://godbolt.org/g/cMaQm2

  • GCC 4.4.7和4.5.3永远不会忽略volatile.
  • 对于数组大小为1,2和4,GCC 4.6.4和4.7.3忽略volatile.
  • GCC 4.8.1直到4.9.2忽略数组大小1和2的volatile.
  • GCC 5.1直到5.3忽略数组大小1,2,4,8的volatile.
  • GCC 6.1只是忽略任何数组大小(一致性的奖励点).

我测试过的任何其他编译器(clang,icc,vc)都会生成一个人们期望的存储,包括任何编译器版本和任何数组大小.所以在这一点上我想知道,这是一个(非常古老而严重的?)GCC编译器错误,或者是标准中volatile的定义,它不确定这实际上是符合行为的,这使得编写便携式基本上是不可能的" SecureZeroMemory"功能?

编辑:一些有趣的观察.

#include <cstddef>
#include <cstdint>
#include <cstring>
#include <atomic>

void callMeMaybe(char* buf);

void volatileZeroMemory(volatile void* ptr, std::size_t size)
{
    for (auto bytePtr = static_cast<volatile std::uint8_t*>(ptr); size-- > 0; )
    {
        *bytePtr++ = 0;
    }

    //std::atomic_thread_fence(std::memory_order_release);
}

std::size_t foo()
{
    char …
Run Code Online (Sandbox Code Playgroud)

c c++ standards gcc

87
推荐指数
2
解决办法
4507
查看次数

严格的混叠和对齐

我需要一种安全的方法来在任意POD类型之间进行别名,符合ISO-C++ 11,明确考虑n3242或更高版本的3.10/10和3.11.这里有很多关于严格别名的问题,其中大部分都是关于C而不是C++.我找到了一个使用联合的C的"解决方案",可能使用了这个部分

联合类型,包括其元素或非静态数据成员中的上述类型之一

从那我建立了这个.

#include <iostream>

template <typename T, typename U>
T& access_as(U* p)
{
    union dummy_union
    {
        U dummy;
        T destination;
    };

    dummy_union* u = (dummy_union*)p;

    return u->destination;
}

struct test
{
    short s;
    int i;
};

int main()
{
    int buf[2];

    static_assert(sizeof(buf) >= sizeof(double), "");
    static_assert(sizeof(buf) >= sizeof(test), "");

    access_as<double>(buf) = 42.1337;
    std::cout << access_as<double>(buf) << '\n';

    access_as<test>(buf).s = 42;
    access_as<test>(buf).i = 1234;

    std::cout << access_as<test>(buf).s << '\n';
    std::cout << access_as<test>(buf).i << '\n';
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,可以肯定的是,该计划是否符合标准?*

它没有给出任何警告,并且在使用MinGW/GCC 4.6.2进行编译时工作正常: …

c++ strict-aliasing unions type-punning c++11

19
推荐指数
3
解决办法
6098
查看次数

为什么函数地址不是常量表达式

有没有办法在常量表达式中使用函数地址?

void foo()
{}

int main()
{
  static_assert(&foo, "test error");
}
Run Code Online (Sandbox Code Playgroud)

这不会编译.

错误C2057:预期的常量表达式

这背后的意图是我想在编译时比较两个函数地址.

c++ compile-time constant-expression

12
推荐指数
1
解决办法
534
查看次数

让编译器生成adc指令

是否有任何方法可以让Clang,GCC或VS仅使用Standard-C++(98/11/14)生成adc(带有进位)指令?(编辑:我的意思是在x64模式下,如果不清楚则很抱歉.)

c++ compiler-construction optimization assembly

9
推荐指数
1
解决办法
1010
查看次数

std :: unordered_set中元素的要求

std::unordered_set<my_type> my_set;
Run Code Online (Sandbox Code Playgroud)

my_type必须满足哪些要求?(除了std :: hash的专业化)

c++ unordered-set c++11

7
推荐指数
1
解决办法
1047
查看次数

等待atomic_bool

我有两个线程和一个由第二个线程设置的标志.我可以使用atomic_bool,但我希望能够等待*在第一个线程上设置标志.我怎样才能做到这一点?

我不能使用condition_variable我猜,因为如果第二个线程notify_one在第一个线程开始等待之前调用,则线程将不会唤醒.

此外,检查标志是否已经设置应该相当快.我想这应该很简单,但我只是卡住了,所以我在这里问.提前致谢.

*编辑:当然阻止,不忙 - 等待.对不起,如果不清楚.

c++ multithreading atomic c++11

6
推荐指数
2
解决办法
7439
查看次数

将字符串移动到矢量

有没有办法内容从std :: string移动到std :: vector?我认为现在在语言中使用rvalue-references,这个操作有时非常有用.

c++ string vector c++11

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