You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将静态数组声明为指针为何引发Cortex-A9的数据中止错误?

问题分析:Cortex-A9上数组与指针extern声明不匹配导致数据中止错误

问题场景

在ZYNQ 7000(Cortex-A9)平台上,将网络接收的数据存入RAM静态数组时出现异常:

  • 当network.c中用extern char *dataBuffer;声明外部数组时,拷贝过程触发数据中止错误,且错误固定在recvLen=196172时发生
  • 改用extern char dataBuffer[16777216];声明则运行正常
    使用编译器为arm-none-eabi-gcc。

相关代码

data.c

char dataBuffer[16777216];

network.c

#include <string.h>

extern char *dataBuffer; // 触发数据中止错误
// extern char dataBuffer[16777216]; // 正常运行

int recvLen = 0;

int IsLengthValid(int recvLen, int len);

void OnReceivingData(const char *data, int len){
    if(IsLengthValid(recvLen,len)){
        memcpy(&dataBuffer[recvLen],data,len);
        recvLen += len;
    }
}

根本原因:数组与指针的本质类型不匹配

C语言中数组名和指针看似相似,但本质完全不同:

  1. 在data.c中,dataBuffer是静态字符数组,它本身是数组首元素的常量地址,编译器为它分配了16MB的连续RAM空间,数组名直接代表这个空间的起始地址(不是一个占用内存的指针变量)。
  2. 错误声明为extern char *dataBuffer;时,编译器会把dataBuffer当成一个32位指针变量(Cortex-A9是32位架构,指针占4字节内存),而非数组的起始地址。

错误的内存访问逻辑

当执行&dataBuffer[recvLen]时,实际操作完全偏离预期:

  • 编译器会尝试读取dataBuffer这个“指针变量”的值,但这里根本不存在指针变量——它把数组的起始地址区域当成了指针变量的存储位置,读取到的是数组前4字节的内容(假设数组初始为0,读取到的“指针值”就是0x00000000)。
  • 加上recvLen的偏移量后,访问地址变为0x0003001C(196172的十六进制值),这个地址大概率属于未映射RAM、外设空间或无访问权限的区域,直接触发硬件层面的数据中止异常。

为什么错误固定在recvLen=196172时触发?

当recvLen累计到196172时,计算出的访问地址0x0003001C刚好落在了你的系统中未配置访问权限的地址范围,此时第一次触发硬件异常,程序直接终止,所以错误总是停在这个数值上。

正确解决方式

必须保证extern声明与变量定义的类型完全一致:

  • 数组定义对应数组声明:可以写extern char dataBuffer[];(省略长度也有效),或带完整长度的声明
  • 指针定义才对应指针声明

内容的提问来源于stack exchange,提问作者Jackoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 15:12:41