小编Dan*_*und的帖子

使用ref arg获取lambda的std :: thread无法编译

我正在阅读C++并发性.第2.4章描述了parallell_accumulate算法.

我尝试 - 作为一个学习实验 - 用一般的lambda替换那里使用的仿函数.

我已将编译错误提炼为:

#include <thread>

template <typename T>
struct f {
    void operator() (T& result) { result = 1;}
};

int main() {
    int x = 0;
    auto g = [](auto& result) { result = 1; };

    std::thread(f<int>(), std::ref(x));  // COMPILES
    std::thread(g, std::ref(x));         // FAILS TO COMPILE
}
Run Code Online (Sandbox Code Playgroud)

错误消息:

 In file included from /usr/include/c++/4.9/thread:39:0,
                 from foo.cpp:1:
/usr/include/c++/4.9/functional: In instantiation of ‘struct std::_Bind_simple<main()::<lambda(auto:1&)>(std::reference_wrapper<int>)>’:
/usr/include/c++/4.9/thread:140:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = main()::<lambda(auto:1&)>&; _Args = …
Run Code Online (Sandbox Code Playgroud)

c++ generics lambda c++14

12
推荐指数
2
解决办法
2381
查看次数

为什么在使用namespace指令时没有为函数预先添加名称空间?

这个c ++文件......

namespace foo {
    class C {
        void m();
    };
    void f();
}

using namespace foo;

void C::m() {}
void f() {}
Run Code Online (Sandbox Code Playgroud)

..使用以下符号编译到目标文件:

$ g++ foo.cpp  -c
$ nm foo.o  -C
000000000000000a T f()
0000000000000000 T foo::C::m()
Run Code Online (Sandbox Code Playgroud)

为什么要C::m()?预先添加命名空间,但不是f()

(II代替using namespace foo使用,namespace foo {...}然后两个名字都有foo前缀).

c++ namespaces linkage

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

如何从time_t中提取小时数?

我想从表示纪元以来的秒数的time_t值中提取小时,分钟和秒作为整数值.

小时值不正确.为什么?

#include <stdio.h>
#include <time.h>

#include <unistd.h>

int main()
{
    char buf[64];

    while (1) {
        time_t t = time(NULL);
        struct tm *tmp = gmtime(&t);

        int h = (t / 360) % 24;  /* ### My problem. */
        int m = (t / 60) % 60;
        int s = t % 60;

        printf("%02d:%02d:%02d\n", h, m, s);

        /* For reference, extracts the correct values. */
        strftime(buf, sizeof(buf), "%H:%M:%S\n", tmp);
        puts(buf);
        sleep(1);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出(小时应为10)

06:15:35
10:15:35

06:15:36
10:15:36

06:15:37
10:15:37
Run Code Online (Sandbox Code Playgroud)

c time time-t

7
推荐指数
2
解决办法
2万
查看次数

存储缓冲区和行填充缓冲区如何相互作用?

我正在阅读 MDS 攻击论文RIDL:Rogue In-Flight Data Load。他们讨论了 Line Fill Buffer 如何导致数据泄漏。有关于 RIDL 漏洞和负载的“重放”问题讨论了漏洞利用的微架构细节。

阅读该问题后,我不清楚的一件事是,如果我们已经有了存储缓冲区,为什么还需要行填充缓冲区。

John McCalpin 在WC-buffer 与LFB 有什么关系?中讨论了存储缓冲区和行填充缓冲区是如何连接的在英特尔论坛上,但这并没有真正让我更清楚。

对于存储到 WB 空间,存储数据将保留在存储缓冲区中,直到存储退出之后。退役后,数据可以写入 L1 数据缓存(如果该行存在且具有写入权限),否则会为存储未命中分配一个 LFB。LFB 最终会收到缓存行的“当前”副本,以便它可以安装在 L1 数据缓存中,并且可以将存储数据写入缓存。合并、缓冲、排序和“捷径”的细节尚不清楚......与上述合理一致的一种解释是 LFB 用作缓存行大小的缓冲区,其中存储数据在发送到L1 数据缓存。至少我认为这是有道理的,但我可能忘记了一些事情......

我最近才开始阅读乱序执行,所以请原谅我的无知。这是我关于商店如何通过商店缓冲区和行填充缓冲区的想法。

  1. 存储指令在前端被调度。
  2. 它在存储单元中执行。
  3. 存储请求被放入存储缓冲区(地址和数据)
  4. 无效的读取请求从存储缓冲区发送到缓存系统
  5. 如果未命中 L1d 缓存,则将请求放入行填充缓冲区
  6. Line Fill Buffer 将无效读取请求转发到 L2
  7. 某些缓存接收无效读取并发送其缓存行
  8. 存储缓冲区将其值应用于传入的缓存行
  9. 嗯?行填充缓冲区将条目标记为无效

在此处输入图片说明

问题

  1. 如果存储缓冲区已经存在,我们为什么还需要行填充缓冲区来跟踪超出的存储请求?
  2. 我的描述中事件的顺序是否正确?

x86 cpu-architecture cpu-cache micro-architecture cpu-mds

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

如何推理类似 malloc 的函数的严格别名

AFAIK,在三种情况下可以使用别名

  1. 仅限定符或符号不同的类型可以相互别名。
  2. 结构或联合类型可以为其中包含的类型指定别名。
  3. 将 T* 转换为 char* 就可以了。(不允许相反)

在阅读John Regehrs 博客文章中的简单示例时,这些是有意义的,但我不确定如何推理较大示例(例如类似 malloc 的内存安排)的别名正确性。

我正在阅读Per Vognsens 重新实现Sean Barrets弹性缓冲区。它使用类似 malloc 的模式,其中缓冲区在其前面具有关联的元数据。

typedef struct BufHdr {
    size_t len;
    size_t cap;
    char buf[];
} BufHdr;
Run Code Online (Sandbox Code Playgroud)

通过从指针减去偏移量来访问元数据b

#define buf__hdr(b) ((BufHdr *)((char *)(b) - offsetof(BufHdr, buf)))
Run Code Online (Sandbox Code Playgroud)

这是原始buf__grow函数的一个稍微简化的版本,它扩展了缓冲区并将 buf 作为void*.

void *buf__grow(const void *buf, size_t new_size) { 
     // ...  
     BufHdr *new_hdr;  // (1)
     if (buf) {
         new_hdr = xrealloc(buf__hdr(buf), new_size);
     } else {
         new_hdr = xmalloc(new_size); …
Run Code Online (Sandbox Code Playgroud)

c strict-aliasing

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

在gdb中使用带有throw语句的单步执行功能不会带我去捕捉语句

我正在尝试逐步完成C ++程序。它在较低的层中引发了异常,但是我无法让gdb调试器将我带到catch语句。一种解决方法是向其注册捕获点,(gdb) catch catch但是必须记住始终这样做很笨拙,这将导致程序在较低层的每个捕获语句链处暂停。

这是一个复制品,以说明我的观点。对于用g++ foo.cpp -g -o foo.. 编译的程序

#include <cstdio>

void f() {
    throw 42;
}
int main(int argc, char *argv[])
{
    try {
        throw 42;
        //f();
        printf("after throw\n");
    } catch (...) {
        printf("in catch stmt\n");
    }
    printf("after try-catch stmt\n");
}
Run Code Online (Sandbox Code Playgroud)

.. Gdb的工作与我预期的一样:当我跨过throw语句时,下一条语句就是catch。

$ gdb -q foo
Reading symbols from foo...done.
(gdb) start
Temporary breakpoint 1 at 0x912: file foo.cpp, line 9.
Starting program: /home/dannas/foo
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdd88) at foo.cpp:9
9 …
Run Code Online (Sandbox Code Playgroud)

c++ gdb exception try-catch throw

5
推荐指数
0
解决办法
78
查看次数

避免使用内联asm优化远离变量

我正在阅读预防编译器优化,同时描述Chandler Carruths 如何clobber()escape()来自 CppCon 2015:Chandler Carruth"调优C++:基准测试,CPU和编译器!哦我的!".影响编译器.

从阅读那里,我假设如果我有一个输入约束,如"g"(val),那么编译器将无法优化val.但是在g()下面,没有生成代码.为什么?

如何doNotOptimize()重写以确保生成代码g()

template <typename T>
void doNotOptimize(T const& val) {
  asm volatile("" : : "g"(val) : "memory");
}

void f() {
  char x = 1;
  doNotOptimize(&x);    // x is NOT optimized away
}

void g() {
  char x = 1;
  doNotOptimize(x);     // x is optimized away
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/g/Ndd56K

c++ assembly inline-assembly performance-testing compiler-optimization

3
推荐指数
1
解决办法
634
查看次数