本文介绍了uint8_t数组中整数(或其他)类型的字节对齐的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为使用uint8_t数组的微控制器编写内存管理器.从该池中,它将所需大小的内存分配给用户.

I am writing a memory manager for microcontrollers that uses a uint8_t array for the pool. From this pool, it allocates memory of the requested size to the user.

我正在寻找其他的内存实现. Contiki 有一个名为 mmem .他们在文档中指出:

I am looking at other memory implementations. Contiki has one named mmem. In their documentation they state:

相反,不能指向由mmem_alloc()分配的内存的指针 安全地转换为除char *,有符号的char *或以外的任何指针类型 未签名的字符*.

Instead, the pointer to the memory allocated by mmem_alloc() cannot be safely converted to any pointer type other than char*, signed char* or unsigned char*.

这意味着如果分配的内存块用于存储 struct类型的内容,无论该struct必须声明为packed 或必须使用memcpy().使用GCC可以指定打包的结构 使用以下语法:

This means that if the allocated memory chunk is used to store the contents of a struct type, either the struct must be declared packed or memcpy() must be used. With GCC a packed struct can be specified using the following syntax:

...

所以这是我从未意识到的一个大陷阱.

So this is a pretty big gotcha that I was never aware of.

几个问题:

  • 对所有体系结构都是这样吗?我正在阅读 Wikipedia ,他们指出,大多数架构都支持未对齐的数据,这只会减慢速度.

  • Is this true for all architectures? I am reading on Wikipedia and they state that most archetectures support unaligned data, it just slows things down.

  • Contiki链接讨论打包结构作为解决对齐问题的一种方法.有没有办法打包"uint16_t"或"int32_t"值?我向用户提供了用于常见数据访问的宏,因此这可能是一种可能的解决方案

  • The Contiki link talks about packing the structs as a way to get around the alignment problem. Is there a way to "pack" a uint16_t or int32_t value? I provide macros to the user for common data access, so this could be a possible solution

    ARM处理器是否支持自动不对齐访问? x86怎么样?真的有这么多陷阱吗?

    Do ARM processors support automatic unaligned access? How about x86? Are there really this many gotchas?

    我应该只允许对齐的分配请求,并填写其他任何数据吗?这对我来说很烦.

    Should I just only allow aligned allocation requests, and fill in whatever other data? This would be very annoying for me.

    感谢您提供有用的答案,但是由于内存管理器的工作原理,我无法在用户要求对齐的地方写一些东西(它必须通过移动数据进行碎片整理-我不愿意增加担心对齐的复杂性是一些数据,因为这将显着影响整个系统的性能

    Thank you for the helpful answers, however I cannot write something where the user requests alignment because of how the memory manager works (it has to defragment by moving data -- I am not willing to add the complexity of worrying about what alignment some data is, as that will significantly effect the performance of the whole system)

    似乎在我的系统(Ubuntu)和我所针对的ARM内核上,数据对齐都不是问题.

    It seems that on both my system (Ubuntu) and the ARM core I am targeting, data alignment is not an issue.

    此处:

    ...

    此外,以下代码可以在我的(x86_64 Ubuntu 14.04)系统上执行您想做的事情:

    Also, the following code does as you would want it to do on my (x86_64 Ubuntu 14.04) system:

    #include "stdio.h"
    
    int main(){
        char data[100];
        unsigned int *value;
        // Some random data
        unsigned int check = (unsigned int)0x324FE23A;
    
        // make the pointer unaligned
        value = (unsigned int *)(data + 1);
        *value = check;
        printf("bool=%u, value=%x, check=%x\n", *value==check, *value, check);
    
        return 0;
    }
    

    当我编译并运行它时:

    $ cc  playground  cc align.c && ./a.out
    bool=1, value=324fe23a, check=324fe23a
    

    解决方案:

    我将添加一个预编译器标志,以请求以文字形式满足请求,以便所有数据自动对齐.但是,对于我当前针对的系统,这没有必要.

    I will add a precompiler flag to request that requests are fulfilled in words so that all data is automatically aligned. However, for the systems I am currently targeting this should not be necessary.

    悬而未决的问题:

    如果有人知道该怎么做:

    If anybody knows a way to do:

    #define tm_uint16_p(index)   ((uint16_t *)tm_void_p(index))
    

    在某种程度上,是否对齐tm_void_p(index)都无关紧要,那样就太好了.

    In a way that it will never matter if tm_void_p(index) is aligned then that would be great.

    注意:上面只是将索引转换为void指针,然后将其强制转换为uint16_t指针.显然,在某些系统上,这将由于对齐问题而失败-它们是一种指定编译器只需对其进行处理的方法吗?

    Note: the above just converts an index into a void pointer, then casts it as a uint16_t pointer. Obviously on some systems this will fail due to alignment issues -- is their a way to specify to the compiler to just deal with it?

    推荐答案

    并非所有处理器都正确.

    It's not true for all processors.

    如果我正在设计低级API,那么在需要处理的处理器上,我会做类似的事情void *my_alloc(size_t size, size_t align)

    If I were designing the low level API, on a processor where this mattered, I'd do something likevoid *my_alloc(size_t size, size_t align)

    如果调用者正在处理字符数组,则它们传递的align为1.对于各种小类型,它们传递的是sizeof(short)sizeof(int)等.

    If callers are manipulating character arrays, they pass an align of 1. For various small types they pass sizeof(short), sizeof(int) etc.

    然后给他们分配一个笨拙的分配器,其中align是MIN(roundup_to_power_of_2(size), SIZE_ON_THIS_ARCH_THATS_ALWAYS_GOOD_ENOUGH)

    Then give them an allocator for the clueless, where align is MIN(roundup_to_power_of_2(size), SIZE_ON_THIS_ARCH_THATS_ALWAYS_GOOD_ENOUGH)

    不,round_up_to_power_of_2不是标准函数(或宏);-)

    And no, round_up_to_power_of_2 isn't a standard function (or macro) ;-)

    这篇关于uint8_t数组中整数(或其他)类型的字节对齐的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

  • 08-29 03:34