结构体对齐导致结构体数组大小变化引发的指针越界操作问题.
来源:互联网 发布:mac word 登录 编辑:程序博客网 时间:2024/05/17 06:29
老大昨晚喊我过去帮他看看程序出现的奇怪问题, 挺晚才回去, 所以没来得及写, 今天反刍(恶......)了一下记录
下来. 哈哈.......被人需要果然是一种幸福. -_-||
这个 DSP 程序驱动部分几乎全是员工 Z(已离职) 编写的. Y 工呢, 根据这个基础增加实现了一部分 OS 功能, 如内
存管理,消息, 信号. 之后就没在继续了, 可能是升任管理层了. 我在刚来时, Y 工曾让我看了一段时间的代码. 我
觉得叫 OS 真的很扯, 因为已实现的功能在空转, 核心的进程管理功能没有实现. 程序执行方式还是传统的for(;;)
& while(1).所以, 我把他们全精简掉. 事实证明是对的.
本来可以一直搞这个 C6000 的. 奈何核心板硬件问题迟迟没有解决,项目搁置. 我又被分配到了其他项目的单片机编
程填坑. 擦........扯远了.
-----------------------------------------扯蛋分割线---------------------------------------------------
谈正题:
老大 S 本来对这个 DSP 程序不甚了解, 所以在修改网络处理的相关代码时, 可能没有考虑到对其他代码的影响. 这
大概就是程序维护的大坑.
问题呢是如此...........
原本这个结构体是这样的:
typedef struct { u32 a; u8 b; u8 c; u8 d; u8 e;} VHF;VHF VHF_Channel[15];// 15 * 8 = 120 Bytes
然后呢, 在结构体里增加了一个成员, 用于表示某个通道是否有效. 所以呢变成了这样:
typedef struct { u32 a; u8 b; u8 c; u8 d; u8 e; u8 f;// 增加的成员} VHF;VHF VHF_Channel[15];// 15 * (8 + 4) = 180 Bytes
然后编译链接, 双零; 运行, 死机!!!
插调试器, 设断点, 单步, 发现在某个函数里的 for 循环 i 在从 0 到 15 的过程中,只增加到 13 然后 i 又回到
1 增加, 如此循环, 死在这了, 而且在变成 12 的时候, 更改了函数内其他 3 个变量的值, 这个是不符合逻辑的.
因为循环体内压根就没对这三个变量进行直接或间接的操作.
开始的时候怀疑是栈溢出的问题, 查阅了手册, 根据编译后的 .map 文件(文后附内容)中得出的 RAM unused 大小修
改了 .cmd 文件中 -statck 的大小, 增加一倍(4KB). 这肯定足够了. 烧写调试还是老错误. 其实原来栈空间就有
4KB 大小了. 这个程序是足够的.
不得已, 重新检查, 挨个单步执行查看, 函数内的局部变量值是否符合预期. 当单步执行到一个长度变量(结构体数
组的长度加上其他值)时, 发现了一个错误, 按照申请的 u32 buf[40] 也就是 160 字节. 而这个长度变量居然是
205(正常值应该是 145), 远超过了缓冲区大小.
找到源头发现是因为增加了结构体成员导致的大小变化. 因为编译器默认是按照 4Bytes 对齐原则(word-alignment)
(查看手册是个好习惯), 所以一个结构体就增加了 4 字节. 而 15 个结构体数组就增加了 60 字节. 远超缓冲区大
小了.
所以, 当 for 循环在操作 0-14 的结构体数组时, 指针已经越界操作. 导致的问题就是修改了不该指向的内存
区域. 所以, 才会有不相干变量值的变化.
其实如果结构体仅仅增加一个字节, 也就多了 15 个字节, 总共刚好侥幸到达 160. 侥幸是侥幸, 后果很严重.
合理的做法还是使用编译器指令来强制结构体字节对齐.如
struct __attribute__ ((__packed__)) packed_struct { char c1; int i; char c2; };
结束附上参考的编译器手册对应章节:
.map 文件内容(部分), 手册中有介绍:
****************************************************************************** TMS320C6x Linker PC v7.4.1 ******************************************************************************>> Linked Tue Nov 12 10:47:24 2013OUTPUT FILE NAME: <E:/os_app8023/project/../Debug/project.out>ENTRY POINT SYMBOL: "_c_int00" address: 10012fc0MEMORY CONFIGURATION name origin length used unused attr fill---------------------- -------- --------- -------- -------- ---- -------- VECTOR_RAM 10000000 00000300 00000200 00000100 RWIX TEXT_RAM 10000300 00015000 000131fc 00001e04 RWIX RAM 10015300 0000ad00 00008226 00002ada RWIXSECTION ALLOCATION MAP output attributes/section page origin length input sections-------- ---- ---------- ---------- ----------------.pinit 0 10000300 00000000 UNINITIALIZED..............以下 略
- 结构体对齐导致结构体数组大小变化引发的指针越界操作问题.
- 关于sizeof与#pragma pack导致结构体大小变化的问题
- 结构体和联合体的大小,结构体内存对齐的原因、规则以及柔性数组
- 结构体的大小、元素的对齐
- 结构体对齐和类的大小
- 结构体的大小与内存对齐
- 数据对齐 & 结构体的大小
- 结构体大小的计算,对齐
- 结构体的大小(内存对齐)
- 计算结构体的大小(对齐)
- 结构体对齐的问题
- 结构体的对齐问题
- 结构体对齐问题.
- 结构体对齐问题
- 结构体对齐问题
- 结构体对齐问题
- 结构体对齐问题
- 结构体对齐问题
- 少用触发器规范
- 航班号总结业务
- 色调、亮度和饱和度
- 【JMeter】解决关联值中涉及括号的正则表达式问题
- C++拷贝构造函数详解
- 结构体对齐导致结构体数组大小变化引发的指针越界操作问题.
- linux中断的处理流程
- 基于分区表的物化视图快速刷新以及维护
- ArcGIS10拓扑规则-面规则
- CUDA SDK VolumeRender
- 索引没用上-drop表恢复后,索引改名了
- 修改VS2010安装时的注册信息
- nvl和nvl2函数使用
- MySQL limit实际用法的详细解析