本文介绍了包装结构是否便携?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Cortex-M4微控制器上有一些代码,并想用二进制协议与PC进行通信。目前,我正在使用使用GCC特定打包属性的打包结构。



以下是一个粗略的概述:

  struct Sensor1Telemetry {
int16_t temperature;
uint32_t timestamp;
uint16_t voltageMv;
// etc ...
__attribute __((__ packed__));

结构TelemetryPacket {
Sensor1Telemetry tele1;
Sensor2Telemetry tele2;
// etc ...
__attribute __((__ packed__));

我的问题是:


  • 假设我对MCU和客户端应用程序中的 TelemetryPacket 结构使用了完全相同的定义,上面的代码是否可以在多个平台间移植? (我对x86和x86_64感兴趣,需要它在Windows,Linux和OS X上运行。)

  • 其他编译器是否支持具有相同内存布局的打包结构?使用什么语法?



编辑 b
$ b


  • 是的,我知道打包的结构是非标准的,但它们似乎有用,足以考虑使用它们。
  • 我对C和C ++都很感兴趣,尽管我不认为GCC会以不同的方式处理它们。
  • 这些结构不是继承的,也不会继承任何东西。

  • 这些结构只包含固定大小的整数字段以及其他类似的打包结构。 (我之前已经被花车烧毁了......) 你永远不要使用在内存(硬件寄存器,从文件中读取项目或者在处理器之间传递数据或者在相同处理器的不同软件之间(在应用程序和内核驱动程序之间))之间建立跨越编译域的结构。由于编译器有自由选择对齐的权利,所以你需要麻烦,然后用户可以通过使用修饰符来使其变得更糟。



    不,没有理由假设您可以跨平台安全地执行此操作,即使您针对不同目标(编译器的不同版本以及目标差异)使用相同的gcc编译器版本也是如此。


    $ b $为了减少失败的可能性,首先从最大的项目开始(64位然后是32位,16位然后是最后的任何8位项目)理想情况下,对齐最少32个,也许64个,希望arm和x86可以做到这一点,但是可以随时更改,也可以由编译器从源代码编译器修改默认值。



    现在,如果这是一份工作安全性的工作,那么一定要继续,您可以做定期维护此代码,可能需要为每个目标定义每个结构(因此ARM的结构定义的源代码副本以及另一个f或者x86,或者如果不是立即就需要这个)。然后,你可以调用每一个或每几个产品版本来完成代码的工作......漂亮的小维护时间炸弹会熄灭......



    如果您希望在编译域或处理器之间安全地进行相同或不同体系结构之间的通信,使用一些大小的数组,一串字节流或半字流。显着降低您在路上失败和维护的风险。不要用结构来挑选那些只能恢复风险和失败的项目。



    人们之所以认为这样可以,因为使用了相同的编译器或系列针对相同的目标或家庭(或编译器源自其他编译器选择),因为您了解语言规则,并且实现定义区域的位置最终会发生变化,有时需要数十年的职业生涯,有时需要星期......它的在我的机器上工作的问题......


    I have some code on a Cortex-M4 microcontroller and'd like to communicate with a PC using a binary protocol. Currently, I'm using packed structs using the GCC-specific packed attribute.

    Here is a rough outline:

    struct Sensor1Telemetry {
        int16_t temperature;
        uint32_t timestamp;
        uint16_t voltageMv;
        // etc...
    } __attribute__((__packed__));
    
    struct TelemetryPacket {
        Sensor1Telemetry tele1;
        Sensor2Telemetry tele2;
        // etc...
    } __attribute__((__packed__));
    

    My question is:

    • Assuming that I use the exact same definition for the TelemetryPacket struct on the MCU and the client app, will the above code be portable accross multiple platforms? (I'm interested in x86 and x86_64, and need it to run on Windows, Linux and OS X.)
    • Do other compilers support packed structs with the same memory layout? With what syntax?

    EDIT:

    • Yes, I know packed structs are non-standard, but they seem useful enough to consider using them.
    • I'm interested in both C and C++, although I don't think GCC would handle them differently.
    • These structs are not inherited and don't inherit anything.
    • These structs only contain fixed-size integer fields, and other similar packed structs. (I've been burned by floats before...)

    解决方案

    You should never use structs across compile domains, against memory (hardware registers, picking apart items read from a file or passing data between processors or the same processor different software (between an app and a kernel driver)). You are asking for trouble as the compiler has somewhat free will to choose alignment and then the user on top of that can make it worse by using modifiers.

    No there is no reason to assume you can do this safely across platforms, even if you use the same gcc compiler version for example against different targets (different builds of the compiler as well as the target differences).

    To reduce your odds of failure start with the largest items first (64 bit then 32 bit the 16 bit then lastly any 8 bit items) Ideally align on 32 minimum perhaps 64 which one would hope arm and x86 do, but that can always change as well as the default can be modified by whomever builds the compiler from sources.

    Now if this is a job security thing, sure go ahead, you can do regular maintenance on this code, likely going to need a definition of each structure for each target (so one copy of the source code for the structure definition for ARM and another for x86, or will need this eventually if not immediately). And then every or every few product releases you get to be called in to do work on the code...Nice little maintenance time bombs that go off...

    If you want to safely communicate between compile domains or processors the same or different architectures, use an array of some size, a stream of bytes a stream of halfwords or a stream of words. Significantly reduces your risk of failure and maintenance down the road. Do not use structures to pick apart those items that just restores the risk and failure.

    The reason why folks seem to think this is okay because of using the same compiler or family against the same target or family (or compilers derived from other compilers choices), as you understand the rules of the language and where the implementation defined areas are you will eventually run across a difference, sometimes it takes decades in your career, sometimes it takes weeks...Its the "works on my machine" problem...

    这篇关于包装结构是否便携?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-31 00:25