- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一些打包的结构,我将把它们写入内存映射文件。它们都是 POD。
为了适应我正在做的一些通用编程,我希望能够编写一个 std::tuple
几个打包结构。
我担心写一个 std::tuple
的成员到我映射区域的地址,然后将该地址转换回 std::tuple
会坏掉的。
我写了一个小示例程序,它似乎可以工作,但我担心我有未定义的行为。
这是我的结构:
struct Foo
{
char c;
uint8_t pad[3];
int i;
double d;
} __attribute__((packed));
struct Bar
{
int i;
char c;
uint8_t pad[3];
double d;
} __attribute__((packed));
我定义了一个 std::tuple
这些结构:
using Tup = std::tuple<Foo, Bar>;
为了模拟内存映射文件,我创建了一个带有一些内联存储和大小的小对象:
当添加一个元组时,它使用 placement new 在内联存储中构造元组。
struct Storage
{
Tup& push_back(Tup&& t)
{
Tup* p = reinterpret_cast<Tup*>(buf) + size;
new (p) Tup(std::move(t));
size += 1;
return *p;
}
const Tup& get(std::size_t i) const
{
const Tup* p = reinterpret_cast<const Tup*>(buf) + i;
return *p;
}
std::size_t size = 0;
std::uint8_t buf[100];
};
为了模拟写入文件然后再次读取它,我创建了一个 Storage
对象、填充它、复制它,然后让原始对象超出范围。
Storage s2;
// scope of s1
{
Storage s1;
Tup t1 = { Foo { 'a', 1, 2.3 }, Bar { 2, 'b', 3.4 } };
Tup t2 = { Foo { 'c', 3, 5.6 }, Bar { 4, 'd', 7.8 } };
Tup& s1t1 = s1.push_back(std::move(t1));
Tup& s1t2 = s1.push_back(std::move(t2));
std::get<0>(s1t1).c = 'x';
std::get<1>(s1t2).c = 'z';
s2 = s1;
}
然后我使用 Storage::get
读取我的元组这只是一个 reinterpret_cast<Tup&>
内联存储。
const Tup& s2t1 = s2.get(0);
当我访问元组中的结构时,它们具有正确的值。
此外,通过 valgrind 运行不会抛出任何错误。
reinterpret_cast
安全吗?从我的内联存储到 std::tuple
如果元组最初是在那里更新的(放入一个将被关闭然后重新映射和重新读取的文件中)?内存映射文件:
我使用的实际 存储是一个转换到 boost::mapped_region
上的结构。 .
结构是:
struct Storage
{
std::size_t size;
std::uint8_t buf[1]; // address of buf is beginning of Tup array
};
我是这样投的:
boost::mapped_region region_ = ...;
Storage* storage = reinterpret_cast<Storage*>(region_.get_address());
下面答案中提到的对齐问题会不会有问题?
完整示例如下:
#include <cassert>
#include <cstdint>
#include <tuple>
struct Foo
{
char c;
uint8_t pad[3];
int i;
double d;
} __attribute__((packed));
struct Bar
{
int i;
char c;
uint8_t pad[3];
double d;
} __attribute__((packed));
using Tup = std::tuple<Foo, Bar>;
struct Storage
{
Tup& push_back(Tup&& t)
{
Tup* p = reinterpret_cast<Tup*>(buf) + size;
new (p) Tup(std::move(t));
size += 1;
return *p;
}
const Tup& get(std::size_t i) const
{
const Tup* p = reinterpret_cast<const Tup*>(buf) + i;
return *p;
}
std::size_t size = 0;
std::uint8_t buf[100];
};
int main ()
{
Storage s2;
// scope of s1
{
Storage s1;
Tup t1 = { Foo { 'a', 1, 2.3 }, Bar { 2, 'b', 3.4 } };
Tup t2 = { Foo { 'c', 3, 5.6 }, Bar { 4, 'd', 7.8 } };
Tup& s1t1 = s1.push_back(std::move(t1));
Tup& s1t2 = s1.push_back(std::move(t2));
std::get<0>(s1t1).c = 'x';
std::get<1>(s1t2).c = 'z';
s2 = s1;
}
const Tup& s2t1 = s2.get(0);
const Tup& s2t2 = s2.get(1);
const Foo& f1 = std::get<0>(s2t1);
const Bar& b1 = std::get<1>(s2t1);
const Foo& f2 = std::get<0>(s2t2);
const Bar& b2 = std::get<1>(s2t2);
assert(f1.c == 'x');
assert(f1.i == 1);
assert(f1.d == 2.3);
assert(b1.i == 2);
assert(b1.c == 'b');
assert(b1.d == 3.4);
assert(f2.c == 'c');
assert(f2.i == 3);
assert(f2.d == 5.6);
assert(b2.i == 4);
assert(b2.c == 'z');
assert(b2.d == 7.8);
return 0;
}
最佳答案
您可能喜欢对齐 std::uint8_t buf[100]
存储,因为未对齐的访问是未定义的行为:
aligned_storage<sizeof(Tup) * 100, alignof(Tup)>::type buf;
(最初您有 100 个字节,这是 100 个 Tup
)。
当您映射页面时,它们在 x86 上至少从 4k 边界开始。如果您的存储从页面开始,那么该存储适合任何高达 4k 的 power-2 对齐方式。
I'm worried that writing the members of a
std::tuple
to my mapped region's address, and then later casting that address back to astd::tuple
is going to break.
只要通过映射内存进行通信的应用程序使用相同的 ABI,就可以按预期工作。
关于c++ - 我可以将新的 std::tuple 放入内存映射区域,然后再读回吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52452173/
我有一个包含文件名 和文件路径 的元组列表。我想找到重复的 filename(但 filepath 可能不同),即文件名相同但 filepath 可能不同的元组。 元组列表示例: file_info
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
我有一个包含几个字段的自定义结构,我想在快速 switch 语句中对其进行模式匹配,这样我就可以通过将其中一个字段与另一个字段进行比较来自定义匹配正则表达式。 例如鉴于这种结构: struct MyS
我有一种动态元组结构: template //Should only be tuples class DynamicTuple { vector data; //All data is st
这个问题在这里已经有了答案: What and When to use Tuple? [duplicate] (5 个答案) 关闭 8 年前。 我正在查看 Tuple 的在线示例,但我没有看到任何理
在我的项目中我有很多坐标要处理,在二维情况下我发现(cons x y)的构造比(list x y)快和 (vector x y)。 但是,我不知道如何将 cons 扩展到 3D 或更进一步,因为我没有
我有以下 Scala 代码: def f(x: Int, y: Int): Option[String] = x*y match { case 0 => None case n =>
我的直觉告诉我,在一般情况下,只有宏或复杂类型的体操才能解决这个问题。 Shapeless 或 Scalaz 可以在这里帮助我吗?这是 N=2 问题的具体实例,但我正在寻找的解决方案适用于所有合理的
为什么这段 Scala 代码是这样的: class Test { def foo: (Int, String) = { (123, "123") } def bar: Unit
我是 python 和 pygame 的新手,我正在尝试学习向量和类的基础知识,但在这个过程中我搞砸了,而且我在理解和修复标题中的错误消息方面苦苦挣扎。 这是我的 Vector 类的代码: impor
我正在编写一个程序来打开和读取一个 txt 文件,并在每一行中循环。将第 2 列和第 4 列中的值相乘并将其分配给第 5 列。 A 500.00 A 84.15 ? B 648.80 B 77.61
我知道还有其他几个问题提出了完全相同的问题,但是当我运行时: 导入命令 从 pyDes 导入 * def encrypt(data, password,): k = des(password,
我有一个元组列表,内容如下: >>>myList [(), (), ('',), ('c', 'e'), ('ca', 'ea'), ('d',), ('do',), ('dog', 'ear', '
给定一个 boost::tuple 和 std::tuple,你如何在它们之间进行转换? 也就是说,您将如何实现以下两个功能? template boost::tuple asBoostTuple(
我无法初始化 std::tuple来自 std::tuple 的逐元素元素兼容类型。为什么它不像 boost::tuple 那样工作? #include #include template st
我是 Storm 的新手并且我正在尝试找出如何编写一个 bolt 测试来测试子类 BaseRichBolt 中的 execute(Tuple tuple) 方法。 问题是 Tuple 似乎是不可变的,
如果我有如下元组列表: [('a', 'b'), ('c', 'd'), ('a', 'b'), ('b', 'a')] 我想删除重复的元组(在内容和内部项目顺序方面重复)以便输出为: [('a',
我编写了一个简单的脚本来模拟基于每用户平均收入 (ARPU)、利润率和客户保持客户的年数 (ltvYears) 的客户生命周期值(value) (LTV)。下面是我的脚本。它在“ltvYears =
以下是我的代码,它是一组元组:。输出:设置([(‘A’,20160129,36.44),(‘A’,20160104,41.06),(‘A’,20160201,37.37)])。如何将另一个元组(‘A’
我用以下代码编写了一个程序: import pandas as pd import numpy as np from typing import Tuple def split_data(self,
我是一名优秀的程序员,十分优秀!