请考虑以下代码:
class Foo
{
public:
//class-specific
Foo operator+(Foo& rhs)
{
return Foo(); //Just return a temporary
}
void* operator new(size_t sd)
{
return malloc(sd);
}
};
//global
Foo operator+(Foo& lhs, Foo& rhs)
{
return Foo();
}
void* operator new(size_t sd)
{
return malloc(sd);
}
Run Code Online (Sandbox Code Playgroud)
此代码将无法编译,说明调用不明确,因为它匹配两个运算符:
Foo a, b;
a + b;
Run Code Online (Sandbox Code Playgroud)
但是这个带有new运算符的编译器很好,并且会调用特定于类的运算符.
Foo* a = new Foo();
Run Code Online (Sandbox Code Playgroud)
为什么不导致编译错误?编译器是否以不同方式处理新运算符?(任何对标准的引用都将不胜感激.)
考虑以下两个类:
class B
{
public:
B() { }
B(const B& b) = delete; //Move ctor not implicitly declared
};
class A
{
public:
A() { }
operator B()
{
return B();
}
};
Run Code Online (Sandbox Code Playgroud)
我可以看到为什么这段代码编译得很好:
A a;
B b = a;
Run Code Online (Sandbox Code Playgroud)
遵循复制初始化的规则,对象"a"被转换为类型B的prvalue,因为在C++ 17中不再需要复制构造函数,所以没有错误:
如果T是类类型,并且其他类型的cv-nonqualified版本不是T或从T派生,或者如果T是非类型类型,但是other的类型是类类型,则是用户定义的转换序列可以检查从其他类型转换为T(或从T派生的类型,如果T是类类型并且转换函数可用),并通过重载决策选择最佳的类型.转换的结果,即prvalue临时(直到C++ 17)prvalue表达式(自C++ 17),如果使用转换构造函数,则用于直接初始化对象.最后一步通常是优化的,转换的结果直接在为目标对象分配的内存中构造,但是即使没有使用,也需要访问适当的构造函数(移动或复制).(直到C++ 17)
但是为什么这个直接列表初始化编译呢?
A a;
B b{ a };
Run Code Online (Sandbox Code Playgroud)
我在列表初始化中找不到任何措辞,说明编译器在这种情况下应该尝试将A转换为B. 只考虑构造函数的重载决策:
如果前一阶段没有产生匹配,则T的所有构造函数都参与对由braced-init-list元素组成的参数集的重载解析,并限制只允许非缩小转换
但是在这种情况下,复制构造函数被删除,所以不应该通过重载决策来选择它吗?
为什么LOCK前缀会导致 x86 上的完全障碍?(因此它耗尽了存储缓冲区并具有顺序一致性)
对于LOCK/read-modify-write 操作,不需要完全屏障,对缓存行的独占访问似乎就足够了。这是设计选择还是有其他限制?
考虑以下简单的共享库源代码:
library.cpp:
static int global = 10;
int foo()
{
return global;
}
Run Code Online (Sandbox Code Playgroud)
用-fPICclang中的option 编译,它会导致以下对象汇编(x86-64):
foo(): # @foo()
push rbp
mov rbp, rsp
mov eax, dword ptr [rip + global]
pop rbp
ret
global:
.long 10 # 0xa
Run Code Online (Sandbox Code Playgroud)
由于符号是在库中定义的,因此编译器按预期使用PC相对地址: mov eax, dword ptr [rip + global]
但是,如果我们更改static int global = 10;为int global = 10;具有外部链接的符号,则结果汇编为:
foo(): # @foo()
push rbp
mov rbp, rsp
mov rax, qword ptr [rip + global@GOTPCREL]
mov eax, dword ptr [rax] …Run Code Online (Sandbox Code Playgroud) 关于std::atomic,C++11 标准规定,存储到原子变量将在“合理的时间内”对该变量的加载变得可见。
从 29.3p13 开始:
\n\n\n\n\n实现应该使原子存储在合理的时间内对原子加载可见。
\n
然而,我很想知道在处理基于 MESI 缓存一致性协议(x86、x86-64、ARM 等)的特定 CPU 架构时实际会发生什么。
\n\n如果我对 MESI 协议的理解是正确的,那么一个核心总是会立即读取先前写入/正在由另一个核心写入的值,可能是通过窥探它。(因为写入值意味着发出 RFO 请求,这反过来会使其他缓存行无效)
\n\n这是否意味着当一个线程 A 将一个值存储到 an 中时std::atomic,另一个连续对该原子进行加载的线程 B 实际上总是会观察到 A 在 MESI 架构上写入的新值?(假设没有其他线程正在对该原子执行操作)
\xe2\x80\x9csuccessively\xe2\x80\x9d 我的意思是在线程 A 发出原子存储之后。(修改顺序已更新)
\n我正在尝试对rar存档进行暴力攻击,我需要密码检查尽可能快.我以这种方式从我的程序中调用rarlab的"unrar"命令行实用程序:
unrar t -p[password] archive.rar
Run Code Online (Sandbox Code Playgroud)
它有效,但速度极慢.存档中的加密文件大约300MB,unrar实用程序告诉我只有在测试整个文件大小后才会出现CRC错误(密码错误).(需要10-15秒)
有没有更快的方法来测试存档密码?
我知道重新排序缓冲区可以用作推测执行需求的历史缓冲区,并且它还允许将寄存器重命名为 ROB 条目(以中断命名依赖项,作为寄存器重命名)。
在线阅读资源/手册,似乎存储缓冲区也用于推测执行。如果路径预测错误,ROB 是否足以丢弃值?
c++ ×4
x86 ×2
assembly ×1
brute-force ×1
c++11 ×1
c++14 ×1
c++17 ×1
got ×1
memory-model ×1
mesi ×1
new-operator ×1
passwords ×1
rar ×1
stdatomic ×1
symbols ×1