gpt4 book ai didi

c++ - boost::serialization 中的派生类偏移量计算。有效吗?

转载 作者:行者123 更新时间:2023-12-02 01:06:58 24 4
gpt4 key购买 nike

boost::serialization 包含 this code :

reinterpret_cast<std::ptrdiff_t>(
static_cast<Derived *>(
reinterpret_cast<Base *>(1 << 20)
)
) - (1 << 20)

其目的是计算基类和派生类之间的偏移量。这段代码没有未定义的行为吗?

<小时/>

我之所以这么问,是因为ASAN+UBSAN提示。例如这段代码

#include <iostream>

class Foo { public: virtual void foo() {} };
class Base { public: virtual void base() {} };
class Derived: public Foo, public Base {};

int main()
{
std::cout <<
(reinterpret_cast<std::ptrdiff_t>(
static_cast<Derived *>(
reinterpret_cast<Base *>(1 << 20)
)
) - (1 << 20));
}

编译为(gcc 版本 9.2.1)

g++ -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -g main.cpp

产生此输出

AddressSanitizer:DEADLYSIGNAL
=================================================================
==72613==ERROR: AddressSanitizer: SEGV on unknown address 0x0000000ffff8 (pc 0x0000004012d9 bp 0x7ffd5b3eecf0 sp 0x7ffd5b3eece0 T0)
==72613==The signal is caused by a READ memory access.
#0 0x4012d8 in main main.cpp:13
#1 0x7f74a90d5f42 in __libc_start_main (/lib64/libc.so.6+0x23f42)
#2 0x40112d in _start (/home/.../a.out+0x40112d)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV main.cpp:13 in main

这是误报还是这段代码确实有问题?

<小时/>

更新 09.12.2019:根据 Filipp 的提议和我的实验,此代码似乎有效并且不会产生任何警告:

std::aligned_storage<sizeof(Derived)>::type data;
reinterpret_cast<char*>(&data)
- reinterpret_cast<char*>(
static_cast<Base*>(
reinterpret_cast<Derived*>(&data)));

有人发现这段代码有任何问题吗?如果没有,我会建议 boost

<小时/>

2019 年 12 月 16 日更新:修复 was mergedboost::serialization develop 分支。

最佳答案

正如另一个答案所示,问题是(1 << 20)不是任何对象的地址。使用char[]原则上可以存储 Derived似乎可以解决这个问题:

#include <stdint.h>
#include <stddef.h>
#include <stdio.h>

class Foo { public: virtual void foo() {} };
class Base { public: virtual void base() {} };
class Derived: public Foo, public Base {};

int main() {
alignas (Derived) char const buffer[sizeof(Derived)] = {};
Derived const* const derived = reinterpret_cast<Derived const*>(buffer);
Base const* const base = derived;
ptrdiff_t const delta =
reinterpret_cast<char const*>(derived) -
reinterpret_cast<char const*>(base);
::printf("%td\n", delta);
return 0;
}

Is it a false-positive or does this code really have problems?

根据对标准的严格解读,代码确实表现出 UB,因此从这个意义上说,它不是误报。在实践中,boost 作者和编译器作者都同意这只是指​​针数学,所以无论如何它应该做正确的事情。

编辑:除非涉及的碱基之一是 virtual 。然后强制转换将尝试从 vtable 中读取偏移量。

编辑 2:使用 nullptr产生 0。更改为使用本地对齐缓冲区。

关于c++ - boost::serialization 中的派生类偏移量计算。有效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59216758/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com