小编Muh*_*rma的帖子

std :: launder如何影响容器?

考虑固定大小的向量的以下简化和不完整的实现:

template<typename T>
class Vec {
  T *start, *end;

public:
  T& operator[](ssize_t idx) { return start[idx]; }

  void pop() {
    end--;
    end->~T();
  }

  template<typename... U>
  void push(U... args) {
    new (end) T { std::forward<U>(args)... };
    end++;
  }
};
Run Code Online (Sandbox Code Playgroud)

现在考虑以下T:

struct T {
  const int i;
};
Run Code Online (Sandbox Code Playgroud)

以下用例:

Vec<T> v;
v.push(1);
std::cout << v[0].i;
v.pop();
v.push(2);
std::cout << v[0].i;
Run Code Online (Sandbox Code Playgroud)

索引运算符使用start指针来访问对象.此时的对象被销毁,pop并在其存储位置创建了另一个对象push(2).如果我正确阅读了围绕std :: launder的文档,这意味着v[0]下面一行中的行为是未定义的.


如何使用std :: launder来纠正这段代码?每次使用贴片新品时,我们是否必须开始和结束?stdlib的当前实现似乎使用类似于上面发布的代码.这些实现的行为是否未定义?

c++ undefined-behavior c++17

11
推荐指数
1
解决办法
856
查看次数

C++ 11内存模型是否允许从循环中提升放松的原子载荷?

请考虑以下代码:

#include <atomic>

extern std::atomic<int> i;

void f(void)
{
  while (!i.load(std::memory_order_relaxed))
      ;
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找C++ 11标准的引用,该标准表明编译器不允许将循环转换为

  if (!i.load(std::memory_order_relaxed)) {
    while (1)
      ;
  }
Run Code Online (Sandbox Code Playgroud)

我在这里看过一些讨论,但没有结论.

编辑:这篇文章的先前版本称为循环内部的外部函数.

编辑2:动机:"Effective Java"一书说HotSpot VM执行以下转换:

while (!done)
    i++;
Run Code Online (Sandbox Code Playgroud)

if (!done)
    while (true)
        i++;
Run Code Online (Sandbox Code Playgroud)

即使它是另一个线程完美定义的行为,可以同时更改已完成的变量.

c++ atomic atomicity c++11

11
推荐指数
1
解决办法
485
查看次数

网络通信是否会创建 C++11 意义上的happens-before关系?

假设一个有两个线程(A 和 B)的程序在 Linux 上运行的情况。

int global = 0;

void thread_A(void) {
    atomic_store(&global, 1);
    udp_send_to_CX();
}

void thread_B(void) {
    block_until_udp_recv_from_CX();
    int local = atomic_load(&global);
    assert(local == 1);
}
Run Code Online (Sandbox Code Playgroud)

线程A向另一台计算机CX发送UDP数据包。收到数据包后,CX 将发送一个 UDP 数据包,该数据包将由线程 B 接收。CX 直到收到线程 A 发送的数据包后才会发送 UDP 数据包。

在发送UDP数据包之前,线程A将值1存储在全局变量中。

线程B收到UDP包后,读取全局变量的值。

我的问题是:

线程 B 中的断言是否保证成功。

也就是说,从 C++ 标准的意义上来说,线程 A 中的存储是否发生在线程 B 中的加载之前。

请注意,我们无法对运行线程 A 和线程 B 的机器做出任何假设。线程 A 发送的 UDP 数据包可能通过与线程 B 中用于接收 UDP 数据包的链路不同的链路发送。

线程 A 和 B 也可能使用不同的套接字来发送和接收数据包。

编辑:针对以下一些评论和答案进行澄清:

例如,如果 Linux 内核中有一个全局原子计数器,在发送数据包之前和接收数据包之后立即通过获取-释放顺序递增,那么问题的答案将是“是的,断言总是成功”。例如sendrecv系统调用可以按如下方式实现:

int network_counter …
Run Code Online (Sandbox Code Playgroud)

c++ linux networking multithreading udp

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