问题与哈佛架构平台,空指针 [英] Issue with NULL pointers on Harvard Architecture platform

查看:119
本文介绍了问题与哈佛架构平台,空指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有趣的问题我们遇到了这个星期在这里。

我们都在C哈佛架构的嵌入式平台,其中有16位数据的地址和32位code地址上工作。

当你与函数指针的工作出现问题。如果你有code像

 如果(FP)FP();

 如果(FP!= 0)FP();

一切都很好。

不过,如果你有code像

 如果(!FP = NULL)FP();

然后,因为 NULL 定义为(无效*)0 ,编译器(GCC在这种情况下) a)不警告b)不反对你的函数的16位比较指针,而不是32位的比较。精细只要你的函数指针不会发生躺在一个64K边界上,因此所有低16位为0。

目前,我们有code大片包含对NULL明确的检查。他们中的大多数将数据指针,但其中一些将是函数指针。一个快速的grep为!= NULL == NULL 显示3000的结果,许多要经过人工检查。

所以,我们现在想,这将是要么


  1. 的方式寻找到函数指针(但不是数据指针)被比较的所有情况下(因此我们可以代替具有比较它们对FP_NULL我们将定义为一个32位的0),或


  2. 要重新定​​义NULL以这样一种方式,它会做正确的事。


  3. (或者,我想,到
    更新我们的GCC端口检测和
    正确处理这种情况下)。


我不认为对于1.我能想到的2是重新定义NULL作为0函数指针,这将是绝大多数比较这是对数据非常浪费的唯一的方法适用于任何方法指针。 (32位比较是4条指令,16位比较是1个指令)。

任何想法或建议?


解决方案

在我看来,最简单的方法是通过替换 NULL 所有出现0 。这适用于函数指针(如你所说)和对象指针。

这是一个变种(2)重新定义NULL为纯 0

但事实上,你不能比较 NULL 函数指针是在实现中的错误。 C99指出,空指针常量比较方式对对象和函数指针,而应该NULL扩展到这个常数。

小除了从C-FAQ问题 5.8


  

问:NULL有效的函数指针结果?
  答:是的(但见问题 4.13


混合函数指针与(无效*)0

(A回复至R ..的评论)。我相信使用函数指针和(无效*)0 一起定义良好。在我的推理,我会参考C99草案1256节,但不会把大型零件,以保持它的可读性。它也应适用于C89


  • 6.3.2.3(3)定义整型常量前pression 0 ,并转换为这样的前pressions(无效*)空指针常量的。和:如果空指针常数被转换为一个
    指针类型,所得到的指针,称为空指针,​​被保证比较不等
    一个指向任何对象或函数。

  • 6.8.9定义了 == != 操作数(除其他外)的指针操作数和空指针常量。对于这些:如果一个操作数是一个指针和另一个是
    空指针常数,空指针常数转换为指针的类型。

结论:在 FP ==(无效*)0 ,空指针常数被转换为类型 FP 。这个空指针可以比作 FP 并保证不等于 FP 如果它指向一个功能。分配( = )也有类似的条款,所以 FP =(无效*)0; 也很好定义的C

Interesting issue we came across here this week.

We are working in C on a Harvard Architecture embedded platform, which has 16-bit data addresses and 32-bit code addresses.

The issue occurs when you are working with function pointers. If you have code like

if (fp) fp();

or

if (fp != 0) fp();

everything is fine.

However if you have code like

if (fp != NULL) fp();

then, because NULL is defined as (void *) 0, the compiler (gcc in this case) a) does not warn and b) does a 16-bit comparison against your function pointer instead of a 32-bit comparison. Fine as long as your function pointer doesn't happen to lie on a 64k boundary so all bottom 16 bits are 0.

At the moment we have large swathes of code which contain explicit checks against NULL. Most of them will be data pointers, but some of them will be function pointers. A quick grep for != NULL or == NULL revealed over 3000 results, to many to go through manually to check.

So, what we would like now would be either

  1. a way to find all the cases where function pointers (but not data pointers) are compared (so we can instead have them compare against FP_NULL which we would define as a 32-bit 0), or

  2. to redefine NULL in such a way that it would do the right thing.

  3. (Or, I suppose, to update our gcc port to detect and correctly handle this case).

I can't think of any approach that works for 1. The only approach I can think of for 2 is to redefine NULL as a 0 function pointer, which would be very wasteful for the vast majority of comparisons which are against data pointers. (A 32-bit compare is 4 instructions, a 16-bit compare is 1 instruction).

Any thoughts or suggestions?

解决方案

It seems to me the easiest way is replace all occurrences of NULL by 0. This works for function pointer (as you say) and object pointers.

This is a variant of (2) Redefine NULL to plain 0.

But the fact that you cannot compare function pointers with NULL is a bug in your implementation. C99 states that comparison of the null pointer constant is possible with both object and function pointers, and that NULL should expand to this constant.

Small addition from the C-FAQ question 5.8:

Q: Is NULL valid for pointers to functions?
A: Yes (but see question 4.13)

Mixing function pointers with (void *) 0

(A reply to R..'s comment). I believe using function pointers and (void *) 0 together is well-defined. In my reasoning I will refer to sections of the C99 draft 1256, but will not quote large parts to keep it readable. It should also be applicable to C89.

  • 6.3.2.3 (3) defines the integer constant expression 0 and such an expressions cast to (void *) as null pointer constant. And: "If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function."
  • 6.8.9 defines the == and != operands for (among other) a pointer operand and a null pointer constant. For these: "If one operand is a pointer and the other is a null pointer constant, the null pointer constant is converted to the type of the pointer."

Conclusion: In fp == (void *) 0, the null pointer constant is converted to the type of fp. This null pointer can be compared to fp and is guaranteed to be unequal to fp if it points to a function. Assignment (=) has a similar clause, so fp = (void *) 0; is also well-defined C.

这篇关于问题与哈佛架构平台,空指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆