This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 编译器/TM4C129XNCZAD:由于结构未在4字节边界上对齐而导致未对齐访问用法故障错误

Guru**** 2394435 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/688017/compiler-tm4c129xnczad-unaligned-access-usage-fault-error-due-to-structure-not-being-aligned-on-4-byte-boundary

器件型号:TM4C129XNCZAD

工具/软件:TI C/C++编译器

当执行以下代码行时、我的函数之一会收到一个用法故障错误、指示未对齐的访问:

  *so2est =-1.0F;

so2est 变量是一个传递到函数中的参数。

调用函数将指针传递给结构成员、作为  So2est 参数。 该结构定义为:

struct SO2Result
{
FloatSP fUArrayNorm[5];

FloatSP fUArraySrc1[5];
FloatSP fUArraySrc2[5];

FloatSP fUSArraySrc1[5];
FloatSP fUSArraySrc2[5];FloatSP fUSArraySrc2[5];

FloatSP fMinErrSqAvg;

FloatSP fSO2Estimate;
FloatSP fSO2ErrSq;
};

注:FloatSP 被拼写为 float。

出于某种原因、结构变量即使包含所有浮点成员、也会存储在非4字节对齐的地址:

如您所见、变量的地址为0x20010C3B、传递给函数的成员的地址为0x20019CA3。

我不理解编译器/链接器为何不自动对齐此结构。 我尝试更改 CCS Build>ARM Compiler>Advanced Options>Runtime Model Options>Generate unaligned load 指令并将其存储为 off、但这并没有什么不同。

我还尝试使用#pragma DATA_ALIGN、但由于变量在栈上、因此它不会接受它。

我是否知道如何使支柱正确对齐?

我运行的是 CCS 版本8.0.0.00016和 TI v18.1.0.LTS 编译器版本。

此致、

Dave

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这看起来像是编译器中的错误。  该结构应在4字节边界上对齐、但事实并非如此。  我猜、当函数局部变量、并且栈框上有其他类型的变量位于变量之前时、会出现问题。  对于具有本地结果 SO2Current 函数的源文件、请按照文章 如何提交编译器测试用例中的说明提交测试用例。

    谢谢、此致、

    乔治

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 George 的快速回答。 我将尝试尽快提交测试案例。

    此致、

    Dave

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    供参考、我可以通过将结构声明为静态、暂时解决此问题。 这会导致正确对齐的地址。

    此致、

    Dave
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    此问题发生在包含极其专有代码的源文件中、因此我无法按照您提供的链接中的建议进行操作。 我将尝试在不包含专有信息的单独文件中重新创建问题。

    此致、

    Dave
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我无法从零开始重现问题、因此我从原始文件中尽可能地删除了大部分专有代码。 我将通过私人消息发送预处理的文件。

     结果 SO2Current 结构位于地址 0x2002FB77、如以下调试器输出所示:

    编译器的版本为18.1.0.LTS。 编译器选项包括:

    "C:\\ti\\ccsv8\\utils\\bin\\gmake"-k -j 8 MP_Application/src/MP_TaskO2SatCalc.obj -O

    生成文件:"../mp_Application/src/mp_TaskO2SatCalc.c"
    调用:ARM 编译器
    "c:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.1.LTS/bin/armcl /Firmware/TripleRing/VIO_TIVA /Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uC-CPU /Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uCOS-II/Source /Firmware/TripleRing/VIO_TIVA/COTS/TivaWare/inc /Firmware/TripleRing/VIO_TIVA/Platform/Device/src /Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me --opt_for_speed=0 --include_path="C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.1.LTS/include --include_path="/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/EvalBoards/TI/DK-TM4C129X/BSP --include_path=/Firmware/TripleRing/VIO_TIVA/MP_Application/inc --include_path=/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uC-CPU/ARM-Cortex-M4/CCS /Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uCOS-II/Ports/ARM-Cortex-M4/Generic/CCS /Firmware/TripleRing/VIO_TIVA/COTS/TivaWare/driverlib /Firmware/TripleRing/VIO_TIVA/BSP/inc /Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uC-CPU/ARM-Cortex-M4/CCS --include_trines=/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/EvalBoards/TI/DK-TM4C129X/OS2 --include_path=/Firmware/TripleRing/VIO_TIVA/COTS/Micrium-uCOS-II/Micrium/Software/uC-LIB --include_trate-tr.com.cn"/Firmware/TripleRing/VIO_TIVA/COTS/TivaWare --include_path=/Firmware/TripleRing/VIO_TIVA/Platform/inc --include_path=/Firmware/TripleRing/VIO_TIVA/COTS --include_trate-.com.cn"--include"--include_path=:

    请注意、编译器生成了大量有关声明但未引用变量的警告、因为我删除了引用这些变量的代码。

    我注意到代码的一个有趣之处在于、有一个#pragma pack 指令暂时将 packing 设置为1。 我认为这可能是问题的原因、但删除#pragma 语句没有什么不同。

    希望我提供的信息能让您轻松跟踪问题。

    此致、

    Dave

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您发送测试案例。  这是用户错误。

    其中一个...

    #pragma pack (1)
    

    (笑声) 在看到此结构定义时生效...

    [引用用户="Dave Hohl"]

    结构 SO2Result

    FloatSP fUArrayCombNorm[5];

    FloatSP fUArraySrc1[5];
    FloatSP fUArraySrc2[5];

    FloatSP fUSArraySrc1[5];
    FloatSP fUSArraySrc2[5];

    FloatSP fMinErrSqAvg;

    FloatSP fSO2Estimate;
    FloatSP fSO2ErrSq;
    };


    [/报价]

    由于此结构类型包含所有浮点成员、因此 pack (1)对结构的布局没有影响。  但这确实意味着编译器不会对齐此结构类型变量的基址。  然后、您将此结构变量的其中一个成员的地址传递给其他一些函数。  该函数假定浮点的指针对齐。  不是、事情从那里开始走下坡路。

    修复方法是确保#pragma pack (1)不会对该结构类型生效。

    谢谢、此致、

    乔治

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    嗯、不知怎么说、我发送给您的文件与我之前使用的代码不匹配。 实际上、我曾尝试在位字段定义的两种大小上推送并弹出电池组大小。 我甚至尝试删除 了#pragma pack 语句、但它不起作用。 也许我搞砸了、无意中编译了一个与我想象中不同的文件版本。 我将在星期一回到工作岗位时对此进行研究。

    此致、

    Dave
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、我想我已经弄清楚了正在发生的情况。 我将一些旧代码从 Sourcery CodeBench 编译器移植到 CCS。 该代码有多个实例、其中使用了以下代码:

    #pragma pack (1)

    (笑声) //结构定义

    pragma pack ()

    pragma pack ()指令旨在将打包恢复到其默认状态。 这适用于 Sourcery CodeBench 以及 IAR 和 GCC。 但是、TI 编译器似乎不支持这一点。

    在我正在处理的文件中、即使我完全删除了#pragma pack 语句、我仍然存在对齐问题。 这是因为该文件包含使用#pragma pack 指令的头文件。 因此,我需要更新项目中的所有文件以使用 push/pop,而不是依赖#pragma pack()来恢复默认值。

    也许可以在 TI 数据库中输入一个特性请求、要求使用#pragma pack()恢复默认的软件包设置、以便它与其他常用编译器兼容?

    此致、

    Dave

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我怀疑您不理解#pragma pack 的工作方式。  pack 属性附加到结构类型。  即使#pragma pack (1)的范围由后续的#pragma pack ()结束、也会保留。  例如...

    #pragma pack (1)
    struct struct_type{
    //此处为//*字段定义
    };
    #pragma pack ()
    
    struct struct_type struct_variable; 

    即使 struct_variable 是在#pragma pack (1)范围之外定义的、也会打包。  这是因为 struct_type 已打包。

    谢谢、此致、

    乔治

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、George、

    我明白包装适用于结构定义。 我认为包含浮点数组的结构没有被打包。 但当我查看结构的定义时、我发现它确实位于使用 pack (1)的整个段中。 我不知道代码的原始作者为什么这么做、也不知道为什么它看起来使用 Sourcery 编译器。 但我想我现在知道如何解决问题了。

    感谢你的帮助。

    此致、

    Dave