在MSP430上,当我取消引用空指针时会发生什么?

5

我知道解引用空指针是未定义的 - 但我想知道在特定目标 - MSP430上会发生什么。

我现在没有开发板可以测试这个问题。

如果我这样做(或类似),会发生什么?

int * foo = NULL;
(*foo)++; //Crash?

地址0x0位于SFR范围内,是保留的。

它会生成PUC/POR吗?还是默默地“工作”?

生成的汇编代码为

;int * foo = NULL;
clr.w   R15
;(*foo)++;
inc.w   R15

因此,地址0x0实际上被递增1。

当我在模拟器中运行时,我看到地址0x0处的值从0变为1。我在调试日志中没有收到任何警告,并且程序正常退出。

我正在使用IAR EW430编译器/汇编器/模拟器。


只是为了明确,你正在要求观察未定义行为的行为;这是一个艰巨的任务。如果你手头有实际的硬件,那么这个问题就不会出现,对吗?即使如此,在违规时是否安装了覆盖中断钩子也取决于特定时刻,这将取决于相同的具体时刻吗?(或者你对以上所有内容都有完全控制吗?)。 - WhozCraig
地址0、1是中断使能位。因此,将地址0从值0递增到值1将启用其中一个中断。程序将继续运行。@Nick,你没有阅读MSP430的架构说明书吗?架构规范可以在以下网址找到:http://transfer.cizgi.com.tr/nsaral/mcu-turkey/MSP430_egitim/chapt4.pdf - user3629249
@user3629249 没有,我之前没有看过那个特定的文档。我查看了5系列用户指南并看到“00000h-000FFh-保留用于系统扩展”在内存映射中。不过我本应该做更多的功课,因为我对5系列和1系列都感兴趣。我正在处理两者的旧代码。 - Nick
@KeithThompson 当然,我见过编译器将 NULL 翻译成完全不同的东西(比如 0xFFFF),在汇编中。这个新地址是一些非法访问时会触发重置的东西……一种类似于裸机段错误的情况。我希望这个目标也有这个功能。 - Nick
@Nick:是的,但这不是我想表达的重点。即使空指针被表示为00000000h,给定int *ptr = NULL; int deref = *ptr;,编译器也不需要生成尝试解引用地址零的代码。它可以简单地将其替换为运行时陷阱指令,例如——即使在目标处理器上解引用地址零不会触发陷阱。 - Keith Thompson
显示剩余4条评论
1个回答

6
不仅读写地址0x0不会导致崩溃或重新启动,实际上这是MSP430应用程序经常使用的完全合法的操作。
MSP430内存映射的初始部分保留给I/O端口和控制寄存器:http://en.wikipedia.org/wiki/TI_MSP430#MSP430_address_space 特别地,0x0及其后续地址处的控制寄存器为:
 #define IE1_                  0x0000    /* Interrupt Enable 1 */
 #define IE2_                  0x0001    /* Interrupt Enable 2 */
 #define IFG1_                 0x0002    /* Interrupt Flag 1 */
 #define IFG2_                 0x0003    /* Interrupt Flag 2 */

例如,通过解引用uint8_t *uint16_t *指针将零写入该内存地址将禁用中断。通过解引用uint32_t *写入零也将清除标志。增加这些寄存器的值并没有太多意义,但完全合法。
至少在msp430系列1、系列2和系列4上是这样。通过检查头文件,我无法找到任何映射到Series 5上0x0位置的内容(中断控制寄存器映射到从0x0100开始的区域)。
因此,如果您想捕获代码中解引用空指针的位置,您就得自己动手了。

谢谢解释,这正是我担心的。我看的是系列5头文件,所以我无法弄清楚0x0的用途。 - Nick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接