标签: memory-alignment

用C/C++解析二进制消息流

我正在为二进制协议(Javad GRIL协议)编写解码器.它由大约一百条消息组成,数据格式如下:

struct MsgData {
    uint8_t num;
    float x, y, z;
    uint8_t elevation;
    ...
};
Run Code Online (Sandbox Code Playgroud)

这些字段是ANSI编码的二进制数,它们彼此之间没有间隙.解析此类消息的最简单方法是将输入的字节数组转换为适当的类型.问题是流中的数据是打包的,即未对齐的.

在x86上,这可以通过使用来解决#pragma pack(1).但是,这在某些其他平台上不起作用,或者由于未对齐数据而导致性能开销.

另一种方法是为每种消息类型编写一个特定的解析函数,但正如我所提到的,该协议包含数百条消息.

另一种选择是使用类似Perl unpack()函数的东西并在某处存储消息格式.说,我们可以#define MsgDataFormat "CfffC"再打电话unpack(pMsgBody, MsgDataFormat).这要短得多,但仍然容易出错并且多余.此外,格式可能更复杂,因为消息可以包含数组,因此解析器将是缓慢而复杂的.

有没有共同有效的解决方案?我已经阅读了这篇文章,并用Google搜索,但没有找到更好的方法来做到这一点.

也许C++有一个解决方案?

c c++ binary parsing memory-alignment

6
推荐指数
2
解决办法
7848
查看次数

我如何模拟alignas(T)?

我有一个数组,用作类型对象的底层内存T:

char memory[sizeof T];
.
.
.
new(memory) T(whatever);
Run Code Online (Sandbox Code Playgroud)

如何确保对象memory正确对齐T?在C++ 0x中我可以说:

alignas(T) char memory[sizeof T];
Run Code Online (Sandbox Code Playgroud)

但Visual Studio 2010尚不支持该特定功能.

c++ memory alignment memory-alignment

6
推荐指数
2
解决办法
3269
查看次数

内部FLASH存储器中C结构的对齐

我有一个配置结构我想保存在ARM cortex M3的内部闪存上.根据规格,数据保存在内部闪存中,必须与32bit对齐.因为我有很多boolean和chars在我的结构中,我不想使用32位存储8位...我决定使用__packed预处理器编译指示打包结构,然后当我将它保存为整个结构时,我只需要确保结构大小可被4整除(4个字节= 32位),如果需要,我可以通过添加填充字节来实现.目前,在开发过程中我经常更改结构,并使其与32位对齐,我需要一直更改填充字节.目前,结构看起来很像

typedef __packed struct
{
uint8_t status;
uint16_t delay;
uint32_t blabla;
uint8_t foo[5];
uint8_t padding[...] // this has to be changed every time I alter the structure.
} CONFIG;
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来实现我正在做的事情?我是嵌入式编程的新手,我想确保我没有犯错误.

编辑:请注意.数据在内部闪存结束时保留,因此省略填充将无法正常工作......

c cortex-m3 memory-alignment iar

6
推荐指数
2
解决办法
4402
查看次数

对齐:在具有对齐成员的所有类中警告C4316

今天我通过追踪一个非常规避的腐败漏洞遇到了很多麻烦.
我想如果我真的注意到这些警告就不会那么难找到,但由于我没有找到有关为什么会弹出这个特定警告的相关信息,我让它滑动,这是一个错误.

所以这是Visual Studio 2013给我的有罪警告:

warning C4316: object allocated on the heap may not be aligned 16
Run Code Online (Sandbox Code Playgroud)

当通过const引用将align(16)临时传递给构造函数时生成它,如下面的代码所示:

class Vector
{};

__declspec(align(16)) class VectorA
{};

class Shape
{
public:
    Shape(const Vector& vec) {}
};

class ShapeA
{
public:
    ShapeA(const VectorA& vec) : mVec(vec) {}

private:
    VectorA mVec;
};

int main(int argc, char *argv[])
{
    Shape* shape = new Shape(Vector()); // ok
    ShapeA* shapea = new ShapeA(VectorA()); // warning C4316: 
                           // object allocated on the heap may not be aligned 16 …
Run Code Online (Sandbox Code Playgroud)

c++ memory-alignment heap-corruption

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

现代cpus如何处理跨页不对齐访问?

我试图理解未对齐的内存访问(UMA)如何在现代处理器(即x86-64和ARM体系结构)上工作.我知道我可能遇到UMA问题,从性能下降到CPU故障.我阅读posix_memalign并缓存行.

我找不到的是当我的请求超出页面边界时,现代系统/硬件如何处理这种情况?

这是一个例子:

  1. malloc()是一块8KB的内存.
  2. 假设malloc()没有足够的内存和sbrk()8KB的话.
  3. 内核获取两个内存页(每个4KB)并将它们映射到我的进程的虚拟地址空间(假设这两个页面在内存中不是一个接一个)
  4. movq (offset + $0xffc), %rax 我从第4092字节开始请求8个字节,这意味着我需要从第一页末尾开始的4个字节和从第二页开始开始的4个字节.

物理内存:

---|---------------|---------------|-->
   |... 4b|        |        |4b ...|-->
Run Code Online (Sandbox Code Playgroud)

我需要在页面边界分割的8个字节.

x86-64和ARM上的MMU如何处理这个问题?内核MM中是否有任何机制以某种方式为这种请求做准备?是否有某种保护malloc?处理器做什么?他们取两页吗?

我的意思是完成这样的请求MMU必须将一个虚拟地址转换为两个物理地址.它如何处理这样的请求?

如果我是软件程序员,我应该关心这些事情吗?为什么?

我正在阅读谷歌,SO,drepper的cpumemory.pdf和gorman的Linux VMM书中的很多链接.但它是一个信息的海洋.如果您至少向我提供一些我可以使用的指针或关键字,那将会很棒.

linux arm x86-64 memory-alignment mmu

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

动态分配正确对齐的内存:char 数组上的 new 表达式是否合适?

我遵循 Stefanus Du Toit 的沙漏模式,即在 C++ 中实现 C API,然后再次将其包装在 C++ 中。这与pimpl idiom非常相似,它对用户也是透明的,但可以防止更多与 ABI 相关的问题并允许更广泛的外语绑定。

与实现指针的方法一样,底层对象的大小和布局在编译时不被外界所知,因此它所在的内存必须动态分配(主要是)。然而,与pimpl情况不同,在pimpl情况下,对象已在分配点完全定义,这里它的属性完全隐藏在不透明指针后面。

获得的内存std::malloc是“适合任何标量类型”,这使得它不适合任务。我不确定new-expression。引自链接页面的分配部分:

此外,如果 new 表达式用于分配一个 char 数组或一个 unsigned char 数组,它可能会在必要时从分配函数中请求额外的内存,以保证不大于请求的数组大小的所有类型的对象的正确对齐,如果稍后将一个放入分配的数组中。

这是否意味着以下代码是合规的?

编程接口

size_t object_size      ( void );     // return sizeof(internal_object);
size_t object_alignment ( void );     // return alignof(internal_object);
void   object_construct ( void * p ); // new (p) internal_object();
void   object_destruct  ( void * p ); // …
Run Code Online (Sandbox Code Playgroud)

c++ memory-management memory-alignment

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

使用虚拟继承的地址未对齐

以下显然有效的代码使用UndefinedBehaviorSanitizer sanitiser产生错位的地址运行时错误.

#include <memory>
#include <functional>

struct A{
  std::function<void()> data; // seems to occur only if data is a std::function
} ;

struct B{
  char data; // occurs only if B contains a member variable
};

struct C:public virtual A,public B{

};

struct D:public virtual C{

};

void test(){
  std::make_shared<D>();
}

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

在macbook上编译和执行 clang++ -fsanitize=undefined --std=c++11 ./test.cpp && ./a.out 产生输出 runtime error: constructor call on misaligned address 0x7fe584500028 for type 'C', which requires 16 byte …

c++ memory-alignment virtual-inheritance sanitizer clang++

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

sizeof总是doubleof的倍数?

sizeof(Type)始终整除alignof(Type)

这样的陈述永远是真的吗? sizeof(Type) % alignof(Type) == 0

c++ sizeof memory-alignment

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

Eigen EIGEN_MAKE_ALIGNED_OPERATOR_NEW 的传递效果?

最近,我意识到的潜在问题内存对齐固定大小的矢量化的本征对象

文档所述的正确代码:

class Foo
{
  ...
  Eigen::Vector2d v;
  ...
public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
 
...
 
Foo *foo = new Foo;
Run Code Online (Sandbox Code Playgroud)

我想知道这个代码是否可以?

class Foo2
{
  ...
  Foo foo;
  ...
};
 
...
 
Foo2 *foo = new Foo2; //?
Run Code Online (Sandbox Code Playgroud)

还是应该EIGEN_MAKE_ALIGNED_OPERATOR_NEWFoo2类中再次添加?这就是建议在这里我想:

如果我们添加 EIGEN_MAKE_ALIGNED_OPERATOR_NEW,这只能解决 Cartographer 库本身的问题。该库的用户还必须将 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 添加到包含矢量化 Cartographer 类的类中。这听起来像是一场维护噩梦。

我没有新运算符重载的经验。我认为这个问题更笼统,并且以某种方式与 new 运算符在 C++ 中的工作方式有关。例如,重载的 new 运算符 inFoo是否被默认的 new 运算符 in 调用Foo2?继承呢?如果Foo2从继承Foo,要我们把同样EIGEN_MAKE_ALIGNED_OPERATOR_NEWFoo2? …

c++ memory-alignment new-operator eigen

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

使用 alignas 防止错误共享被破坏

我不习惯在互联网上发布任何问题,所以如果我做错了什么,请告诉我。

简而言之

  1. 如何在 CPU 缓存行大小为 64 字节的 64 位架构上正确防止错误共享?

  2. C++ 'alignas' 关键字和简单字节数组(例如:char[64])的使用如何影响多线程效率?

语境

在研究Single Consumer Single Producer Queue的非常有效的实现时,我在对我的代码进行基准测试时遇到了 GCC 编译器的不合逻辑行为。

全文

我希望有人有必要的知识来解释正在发生的事情。

我目前在 arch linux 上使用 GCC 10.2.0 及其 C++ 20 实现。我的笔记本电脑是带有 i7-7500U 处理器的联想 T470S。

让我从数据结构开始:

class SPSCQueue
{
public:
    ...

private:
    alignas(64) std::atomic<size_t> _tail { 0 }; // Tail accessed by both producer and consumer
    Buffer _buffer {}; // Buffer cache for the producer, equivalent to _buffer2
    std::size_t _headCache { 0 }; // Head cache for the …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading x86-64 memory-alignment false-sharing

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