小编Fla*_*ire的帖子

调试 CMake find_library

是否可以find_library从 CMake调试?

我想要的是经过考虑的路径列表。我的用例是一个像

find_library (FOO_LIBRARY
              NAMES foo foo.so.0)
Run Code Online (Sandbox Code Playgroud)

并有/lib64/libfoo.so.0我的系统上。但是 CMake 没有找到它。我检查了FIND_LIBRARY_USE_LIB64_PATHS设置为TRUE.

cmake

15
推荐指数
1
解决办法
4722
查看次数

Is GCC9 avoiding valueless state of std::variant allowed?

I recently followed a Reddit discussion which lead to a nice comparison of std::visit optimization across compilers. I noticed the following: https://godbolt.org/z/D2Q5ED

Both GCC9 and Clang9 (I guess they share the same stdlib) do not generate code for checking and throwing a valueless exception when all types meet some conditions. This leads to way better codegen, hence I raised an issue with the MSVC STL and was presented with this code:

template <class T>
struct valueless_hack {
  struct tag {}; …
Run Code Online (Sandbox Code Playgroud)

c++ variant c++-standard-library c++17

13
推荐指数
2
解决办法
189
查看次数

从主机访问CUDA全局设备变量

我想知道是否有官方消息来源,为什么以下工作:

#include <iostream>

struct Array{
    int el[10000];
};

__device__ Array devAr;

void test(Array& ar = devAr){
    for(int i=0; i<10000; i++)
        ar.el[i] = i;
    std::cout << ar.el[0] + ar.el[9999] << std::endl;
}

int main(){
    test();
}
Run Code Online (Sandbox Code Playgroud)

如果您尝试直接访问devAr但是通过引用没有这样的警告(有充分理由),则会收到警告"a __device__ variable"devAr"无法在主机函数中直接读取".但在这两种情况下都可以从主机访问变量.所以看来,该变量有一个主机实例.

我需要知道的是:我认为这是理所当然的吗?

其他测试用例显示指针的值:

#include <iostream>
#include <cstdio>

__device__ int devAr[2];

__global__ void foo(){
    printf("Device: %p\n", &devAr);
    devAr[0] = 1337;
}

int main()
{
    devAr[0] = 4;
    std::cout << devAr[0] << std::endl;
    void* ad;
    cudaGetSymbolAddress(&ad, devAr);
    std::cout << ad << " " << &devAr …
Run Code Online (Sandbox Code Playgroud)

c++ cuda global-variables

8
推荐指数
1
解决办法
8528
查看次数

通过在此指针上放置new来重新初始化对象时的未定义行为

我看到了关于Piotr Padlewski的cppcon的演示文稿,说明以下是未定义的行为:

int test(Base* a){
  int sum = 0;
  sum += a->foo();
  sum += a->foo();
  return sum;
}

int Base::foo(){
  new (this) Derived;
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

注意:假设sizeof(Base) == sizeof(Derived)并且foo是虚拟的.

显然这很糟糕,但我很感兴趣为什么它是UB.我确实理解UB访问realloced指针,但他说,这是相同的.

相关问题:`new(this)MyClass();`直接调用析构函数后的未定义行为?在哪里说"ok,如果没有例外" 是否有效直接调用(虚拟)析构函数?它说的new (this) MyClass();结果是UB.(与上述问题相反)

C++使用放置新的未定义行为构造对象两次?它说:

程序可以通过重用对象占用的存储来结束任何对象的生命周期,或者通过使用非平凡的析构函数显式调用类类型的对象的析构函数来结束任何对象的生命周期.对于具有非平凡析构函数的类类型的对象,程序不需要在重用或释放对象占用的存储之前显式调用析构函数; 但是,如果没有显式调用析构函数或者如果没有使用delete-expression(5.3.5)来释放存储,则不应该隐式调用析构函数,并且任何程序都依赖于析构函数产生的副作用有未定义的行为.

这听起来好像没问题.

我在Placement new中找到了另一个新的贴图描述,并使用const成员分配了类

如果在对象的生命周期结束之后并且在重用或释放对象占用的存储之前,则在原始对象占用的存储位置创建新对象,指向原始对象的指针,引用引用原始对象,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,就可以用来操纵新对象,如果:

  • 新对象的存储完全覆盖原始对象占用的存储位置,以及

  • 新对象与原始对象的类型相同(忽略顶级cv限定符),和

  • 原始对象的类型不是const限定的,如果是类类型,则不包含任何类型为const限定的非静态数据成员或引用类型,以及

  • 原始对象是类型为T的派生程度最高的对象,新对象是类型为T的派生程度最高的对象(也就是说,它们不是基类子对象).

这似乎解释了UB.但这是真的吗?

这是不是意味着,我不能拥有std::vector<Base>?因为我假设由于它的预分配std::vector必须依赖placement-news和显式ctors.第4点要求它是最衍生的类型,Base显然不是.

c++ destructor placement-new language-lawyer

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

64位原子添加到CUDA中

atomicAdd我在 CUDA 7 下使用时遇到问题。atomicAdd定义为“ int”、“ unsigned int”和“ unsigned long long int”,说明它使用“32 或 64 位值”。

为了安全起见,在我们的代码中我们使用uint32_tuint64_t。然而 gcc 是这样定义的:

#if __WORDSIZE == 64
typedef unsigned long int   uint64_t;
#else
__extension__
typedef unsigned long long int  uint64_t;
#endif
Run Code Online (Sandbox Code Playgroud)

因此,当我将 an 传递uint64_tatomicAdd它时,它会抱怨,因为它没有为“ unsigned long int”定义。

是否可以uint64_t == long long int按照编程指南中所述假设进行 CUDA 编译?

c++ types cuda atomic word-size

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

cc1plus:任何其他警告均出现无法识别的命令行选项警告

我有一个奇怪的 g++ 行为,当显示任何其他警告时,它会显示有关无法识别的命令行选项的警告。

\n\n

例子:

\n\n
struct Foo{virtual int bar() = 0;};\nstruct Bar:public Foo{int bar() {return 0;} };\n\nint main(){}\n
Run Code Online (Sandbox Code Playgroud)\n\n

编译g++-5 -Wsuggest-override -Wno-c99-extensions -std=c++11 a.cpp甚至g++-5 -Wsuggest-override -Wno-c99-extensions a.cpp显示:

\n\n
a.cpp:2:27: warning: \xe2\x80\x98virtual int Bar::bar()\xe2\x80\x99 can be marked override [-Wsuggest-override]\n struct Bar:public Foo{int bar() {return 0;} };\n                           ^\ncc1plus: warning: unrecognized command line option \xe2\x80\x98-Wno-c99-extensions\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n\n

添加:当我编译时没有警告/错误,g++-5 -Wno-c99-extensions a.cpp因此该选项通过使用 CMAKE 检查CHECK_CXX_COMPILER_FLAG

\n\n

这让我很困扰,因为我们使用 Werror 但通过 Wno-error=... 出现异常,然后当任何(非错误)警告显示为“无法识别的命令行选项”时,它就会退出

\n\n

这是已知的/预期的吗?如何预防?

\n

c++ g++ compiler-warnings suppress-warnings

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

Python 在 float 和 numpy.float64 上舍入的不同舍入行为

我遇到了由浮点精度引起的测试失败,并试图理解它。

简而言之:Python3 round根据类型是 float 还是 numpy.float64 返回不同的值,尽管我认为float==double==float64Python 3和 NumPy 都应该四舍五入到最接近偶数。

这里是例子:

npVal = np.float64(435)/100
pyVal = 435/100
print(round(npVal,1))             // 4.4
print(round(pyVal,1))             // 4.3
print(round(np.float64(pyVal),1)) // 4.4
print(round(float(npVal),1))      // 4.3
Run Code Online (Sandbox Code Playgroud)

我知道 4.35 和 4.4 可能无法完全用 double 表示,但为什么 numpy round 与 Python 不同,尽管它们都使用相同的数据类型并指定相似的函数?我使用显式除法来避免输入舍入错误。

我不确定 4.35 的双精度值是多一点还是少一点,所以我不能说哪些实现是(可能是?)错误的。

有一个类似的问题:奇怪的行为 of numpy.round

其中指出,NumPy“舍入到最接近的偶数”并且“Python 2 和 Python 3 之间的行为发生了变化;Python 3 的行为与 NumPy 相同”。

因此两者都应该做同样的事情并四舍五入到最接近的偶数。因此,如果4.35 是精确浮点数,则 4.4 就是正确答案,并且需要由两者返回。

python floating-point numpy rounding

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

C++ UBSAN 使用派生对象产生误报

我想使用 UBSAN(未定义行为消毒剂),但发现它完全没有价值,因为它会报告许多误报。

例如,一个简单的std::make_shared<int>(42);就足以触发警告,如

地址 0x00000236de70 内的成员访问不指向类型为“_Sp_counted_base”的对象

将此示例简化为 MWE 表明该问题在基类和继承中更为普遍:

例子:

struct Foo{
    int f(){ return g(); }
    virtual int g() = 0;
};

struct Bar: Foo{
    int g(){ return 42; }
};

int main(){
    auto f = new Bar();
    return f->g();
}
Run Code Online (Sandbox Code Playgroud)

编译-fsanitize=undefined并观看

example.cpp:15:16: 运行时错误:地址 0x000000726e70 上的成员调用不指向“Bar”类型的对象

0x000000726e70:注意:对象具有无效的 vptr

请参阅https://godbolt.org/z/0UiVtu

连这些简单的案件都没有妥善处理?我错过了什么吗?我应该如何正确使用 UBSAN 来检查我的代码?(这需要[几乎]没有误报)

编辑:由于 MWE 似乎只适用于 Godbolt,原始代码如下所示:

#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/iostreams/stream.hpp>
using MMStream = boost::iostreams::stream<boost::iostreams::mapped_file_source>;

int main(){
  MMStream stream;
  stream.open("a.out");
  return !stream;
}
Run Code Online (Sandbox Code Playgroud)

编译 …

c++ undefined-behavior ubsan

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

ASAN 检测到与动态加载库共享的类 vtable 的 ODR 违规

我正在开发一个项目,该项目有一个“util”库,其中包含日志记录、断言处理等内容。它被编译成添加了静态库的静态库-fPIC。我还有一个插件系统,其中插件是在运行时通过dlopen. 这些插件和主要可执行文件都使用静态 util 库。

问题:现在我AddressSanitizer: odr-violation在使用 ASAN 时遇到错误。该问题size=40 'vtable for StdStreamWriter'报告了两次,其中 StdStreamWriter 是静态库内部使用的接口的实现。

我非常努力地在 MWE 中重现这一点:

  • 创建一个静态库,公开一些函数
  • 里面使用 std::shared_ptr 中的接口和实现
  • 创建一个共享库链接
  • 创建一个链接静态库和dlopen共享库的可执行文件

CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
project(proj)

set(sanitizer_flags "-fsanitize=address,undefined -fno-omit-frame-pointer")
string(APPEND CMAKE_CXX_FLAGS " ${sanitizer_flags}")
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${sanitizer_flags}")
string(APPEND CMAKE_MODULE_LINKER_FLAGS " ${sanitizer_flags}")

add_library(foo STATIC foo.cpp)
target_compile_features(foo PUBLIC cxx_std_14)
set_target_properties(foo PROPERTIES CXX_EXTENSIONS OFF POSITION_INDEPENDENT_CODE ON)
add_library(lib SHARED lib.cpp)
target_link_libraries(lib foo)
add_executable(main main.cpp)
target_link_libraries(main foo dl)
Run Code Online (Sandbox Code Playgroud)

然而,无论我多么努力,这个问题都不会出现在 MWE 中。

我将差异追溯到以下方面的不同结果nm -C liblib.so …

c++ shared-libraries one-definition-rule address-sanitizer

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

使用 -pthread 如何不违反 ODR 规则?

我最近通过 CFFI 进行了 Python 扩展/包构建,它使用pthread_atfork(和 pthread 互斥锁)但不与 pthread 链接,即既不指定-pthread也不指定-lpthread,因此在具有由 libpthread 链接的静态部分的系统上失败由于缺少符号,链接脚本(而不是纯粹的共享库)。

在考虑正确的修复时,我在编译时偶然发现了-pthread 和 -lpthread 之间差异。因此,-pthread在编译和链接步骤中使用不仅放置-lpthread在正确的位置(在上述设置中至关重要),而且还定义了改变函数定义的预处理器符号。

(第三方)函数的一个例子是boost::datetime::c_time::localtime(...)调用localtime_rstd::localtime

这不是(很可能)违反 ODR 的来源吗?因此,例如编译一个根本不使用线程的简单静态库,-pthread并将其链接到一个使用线程的二进制文件中,因此正在使用-pthread将导致此类函数的不同定义并且是 UB(/IB?)?

然而从我/usr/include/features.h看来

   _REENTRANT, _THREAD_SAFE
      Obsolete; equivalent to _POSIX_C_SOURCE=199506L.
Run Code Online (Sandbox Code Playgroud)

所以问题:

  1. 是否存在/是否由于 ODR 违规-pthread,如果是,为什么(不是避免/故意/疏忽)?
  2. 这些定义不再相关了吗?所以-pthread现在相当于-lpthread(保存展示位置)?
  3. 应该使用什么来构建 Python 的 CFFI 扩展?使用-pthread是困难的,因为编译器相关的命名(-pthread, -pthreads, -mthreads...)

c c++ pthreads one-definition-rule

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