小编Ale*_*iev的帖子

[[nodiscard]] 到函数指针

我想使用第三方函数,它通过充满函数指针的结构提供其 API。例如:

struct S {
    using p_func1 = int(*)(int, int);
    p_func1 func1;
    using p_func2 = int(*)(char*);
    p_func2 func2;
}
Run Code Online (Sandbox Code Playgroud)

第三方库初始化该结构。需要检查这些函数(func1、func2)的返回值,我希望能够以某种方式在属性上体现出来,[[discard]]以确保返回值得到检查。

有什么办法可以做到这一点,同时保持结构的 ABI?

编辑:到目前为止,我能想到的最好的办法就是拥有另一个结构,如下所示:

struct S_wrap {
    S orig;
    [[nodiscard]] int func1(int a, int b){ return orig.func1(a, b); }
    [[nodiscard]] int func2(char* a){ return orig.func2(a); }
}
Run Code Online (Sandbox Code Playgroud)

我希望有更好的东西

c++ c++17 nodiscard

6
推荐指数
1
解决办法
547
查看次数

由于 Spectre Mitigation,Hardware Lock Elision 是否已经一去不复返了?

由于 Spectre 缓解,所有当前 CPU 都禁用了硬件锁定省略是否正确,并且任何尝试使用 HLE 内在函数/指令进行互斥都会导致通常的互斥?

这是否有可能在未来不会有类似 HLE 互斥体的东西来避免像 Spectre 这样的漏洞?

security x86 x86-64 speculative-execution intel-tsx

6
推荐指数
1
解决办法
398
查看次数

为什么 C++20 屏障中存在单独的到达和等待?

C++20std::barrierarrive_and_wait方法,这几乎是每个同步屏障实现都有的。

但它也有单独的arrivewait。为什么会有这些功能?

c++ barrier c++20

6
推荐指数
1
解决办法
332
查看次数

C++ 标准如何使用 memory_order_acquire 和 memory_order_release 防止自旋锁互斥锁中的死锁?

TL:DR:如果互斥体实现使用获取和释放操作,那么实现是否可以像通常允许的那样进行编译时重新排序,并重叠两个应该独立于不同锁的临界区?这将导致潜在的僵局。


假设互斥锁在 上实现std::atomic_flag

struct mutex
{
   void lock() 
   {
       while (lock.test_and_set(std::memory_order_acquire)) 
       {
          yield_execution();
       }
   }

   void unlock()
   {
       lock.clear(std::memory_order_release);
   }

   std::atomic_flag lock; // = ATOMIC_FLAG_INIT in pre-C++20
};
Run Code Online (Sandbox Code Playgroud)

到目前为止看起来还可以,关于使用单个这样的互斥锁:std::memory_order_releasestd::memory_order_acquire.

在这里使用std::memory_order_acquire/std::memory_order_release不应该一见钟情。它们类似于 cppreference 示例https://en.cppreference.com/w/cpp/atomic/atomic_flag

现在有两个互斥锁保护不同的变量,两个线程以不同的顺序访问它们:

mutex m1;
data  v1;

mutex m2;
data  v2;

void threadA()
{
    m1.lock();
    v1.use();
    m1.unlock();

    m2.lock();
    v2.use();
    m2.unlock();
}

void threadB()
{
    m2.lock();
    v2.use();
    m2.unlock();

    m1.lock();
    v1.use();
    m1.unlock();
}
Run Code Online (Sandbox Code Playgroud)

释放操作可以在无关的获取操作之后重新排序(无关操作 == 对不同对象的后续操作),因此执行可以转换如下:

mutex m1;
data  v1;

mutex …
Run Code Online (Sandbox Code Playgroud)

c++ memory-model spinlock language-lawyer stdatomic

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

Clang 默认强制执行 [[nodiscard]] ?

C++17具有nodiscard防止人们忽略函数返回值的属性。

将其添加到代码库中的每个函数中似乎有些过分了。

是否有一个标志告诉 Clang 默认强制执行此操作?

c++ clang nodiscard

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

cmpxchg 是否会在失败时写入目标缓存行?如果不是,对于自旋锁来说它比 xchg 更好吗?

我假设简单的自旋锁不会进入操作系统等待这个问题的目的。

我发现简单的自旋锁通常使用lock xchgorlock bts代替 来实现lock cmpxchg

cmpxchg但是如果期望不匹配,是否会避免写入该值?那么失败的尝试不是更便宜吗cmpxchg

或者即使cmpxchg发生故障也会写入数据并使其他核心的缓存线无效?

这个问题类似于什么具体将 x86 缓存行标记为脏 - 任何写入,还是需要显式更改?,但它是特定的cmpxchg,而不是普遍的。

x86 assembly micro-optimization compare-and-swap cpu-cache

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

从 [[nodiscard]] 中排除函数的返回值

我想将一个类标记为 nodiscard,但将某个函数的返回值排除在 nodiscard 要求之外。这是我的目标:

enum class [[nodiscard]] Result {
  OK1,
  OK2,
  ERROR,
};

[[ok-to-discard]] // This attribute is made up to illustrate my need.
Result doSomethingThatCannotFail() {
  // The function can return OK1 or OK2, but the caller may or may not care.
  // The function cannot return ERROR.
  // Therefore, it's OK to discard this particular Result return value,
  // even though in general Result should not be ignored.
}
Run Code Online (Sandbox Code Playgroud)

我不认为在每个调用站点添加 ok-to-discard 是一个好主意(这由 如何故意丢弃 [[nodiscard]] 返回值? 涵盖):

  • 有很多调用点。最好避免在任何地方添加 …

c++ c++17 nodiscard

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

MSVC 中的 Address Sanitizer:为什么启动时报告错误?

我正在尝试一个使用 Qt 和 MSVC 2019 以及 Address Sanitizer 的项目。我使用 Address Sanitizer 构建了该项目,但没有重建所有库,包括 Qt。

qRegisterResourceData它在资源初始化(在调用堆栈中)时在 Qt 内部崩溃。

这是:

  • 滥用地址清理程序,例如,我也应该用它重建 Qt DLL?
  • Qt 中的一个问题我应该更深入地调查?
  • 已知的 Qt 问题?

我已经在默认情况下由向导创建的小部件应用程序中重新创建了该问题。调用栈如下:

>   KernelBase.dll!RaiseException() Unknown
    QtWidgetsApplication1.exe!__vcasan::OnAsanReport(const char * description, const char * report, bool __throw) Line 602  C++
    QtWidgetsApplication1.exe!__vcasan::ReportCallback(const char * szReport) Line 325  C++
    clang_rt.asan_dbg_dynamic-x86_64.dll!__asan::ScopedInErrorReport::~ScopedInErrorReport(void)    Unknown
    clang_rt.asan_dbg_dynamic-x86_64.dll!__asan::ReportMallocUsableSizeNotOwned(unsigned __int64,struct __sanitizer::BufferedStackTrace *)  Unknown
    clang_rt.asan_dbg_dynamic-x86_64.dll!__asan::asan_malloc_usable_size(void const *,unsigned __int64,unsigned __int64)    Unknown
    clang_rt.asan_dbg_dynamic-x86_64.dll!_recalloc()    Unknown
    ucrtbased.dll!_register_onexit_function::__l2::<lambda>() Line 112  C++
    ucrtbased.dll!__crt_seh_guarded_call<int>::operator()<void <lambda>(void),int <lambda>(void) &,void <lambda>(void)>(__acrt_lock_and_call::__l2::void <lambda>(void) && setup, _register_onexit_function::__l2::int <lambda>(void) & …
Run Code Online (Sandbox Code Playgroud)

c++ qt visual-c++ address-sanitizer

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

是否保证 x86 取指令是原子的,以便用短跳转重写指令对于并发线程执行是安全的?

我认为热补丁假设用 2 字节跳转覆盖任何 2 或更多字节长的指令对于并发执行相同的代码是安全的。

因此取指令被假定为原子的。

考虑到使用前缀可以有超过 8 字节的指令,并且它可以跨越任何对齐的边界,它确实是原子的吗?(或者热补丁是否依赖于函数开始的 16 字节对齐?如果是这样,那么大小超过 8 字节又是什么?)


上下文:LLVM 在https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/interception/interception_win.cpp中拦截了 API 函数。这至少用于 Address Sanitizer,也许也用于其他用途。它将 HotPatch 实现为第三种方法(第 61 行):

// 3) HotPatch
//
//    The HotPatch hooking is assuming the presence of an header with padding
//    and a first instruction with at least 2-bytes.
//
//    The reason to enforce the 2-bytes limitation is to provide the minimal
//    space to encode a short jump. HotPatch technique is only rewriting one …
Run Code Online (Sandbox Code Playgroud)

x86 atomic self-modifying hotpatching

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

英特尔 JCC 勘误表 - 用于缓解的前缀有什么影响?

英特尔建议使用指令前缀来减轻 JCC 勘误对性能的影响。

如果使用 MSVC 进行编译,则会/QIntel-jcc-erratum遵循建议,并插入带前缀的指令,如下所示:

3E 3E 3E 3E 3E 3E 3E 3E 3E 48 8B C8   mov rcx,rax ; with redundant 3E prefixes
Run Code Online (Sandbox Code Playgroud)

他们说,当前缀不可用时,MSVC 会求助于 NOP。

Clang 有-mbranches-within-32B-boundaries这个选项,nop如果需要,它更喜欢多字节(https://godbolt.org/z/399nc5Msq通知xchg ax, ax

3E 前缀的后果是什么,具体来说:

  • 为什么 Intel 推荐这个而不是多字节 NOP?
  • 对于未受影响的 CPU 会产生什么后果?
  • 据报道,AMD 上的程序运行速度更快/QIntel-jcc-erratum,可能的解释是什么?

x86 assembly intel cpu-architecture micro-optimization

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