C标准兼容的方式来访问空指针的地址? [英] C standard compliant way to access null pointer address?

查看:221
本文介绍了C标准兼容的方式来访问空指针的地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C,deferencing的的空指针的是未定义行为,但空指针值有一点重presentation,在某些架构使得它指向一个有效的地址(如地址0 )。结果
让我们把这个地址的空指针地址的,为了清楚起见。

In C, deferencing the null pointer is Undefined Behavior, however the null pointer value has a bit representation that in some architectures make it points to a valid address (e.g the address 0).
Let's call this address the null pointer address, for the sake of clarity.

假设我想用C编写一个软件,在奔放的访问内存的环境。进一步假设我想在空指针的地址写一些数据:我怎么会实现,在一个标准兼容的方式

Suppose I want to write a piece of software in C, in an environment with unrestrained access to memory. Suppose further I want to write some data at the null pointer address: how would I achieve that in a standard compliant way?

例的情况下(IA32E):

#include <stdint.h>

int main()
{
   uintptr_t zero = 0;

   char* p = (char*)zero;

   return *p;
}

这code当用gcc编译的 -O3 的为IA32E被改造成

This code when compiled with gcc with -O3 for IA32e gets transformed into

movzx eax, BYTE PTR [0]
ud2

由于UB(0是位重新空指针的presentation)。

due to UB (0 is the bit representation of the null pointer).

由于C靠近底层编程,我相信一定有访问空指针的地址,并避免UB的方式。

Since C is close to low level programming, I believe there must be a way to access the null pointer address and avoid UB.

只是要清楚结果
我问什么标准有说这个,不会如何在实现定义的方式实现这一目标。结果
我知道后者的答案。

Just to be clear
I'm asking about what the standard has to say about this, NOT how to achieve this in a implementation defined way.
I know the answer for the latter.

推荐答案

我读(部分)C99标准来清除我的脑海里。我发现,是对我自己的问题感兴趣的部分,我写这作为参考。

I read (part of) the C99 standard to clear my mind. I found the sections that are of interest for my own question and I'm writing this as a reference.

免责声明结果
我是一个绝对的初学者,90%以上的我已经写了什么是错的,是没有意义的,或者可能会破坏你的烤面包机。我也试着做一个理由出来的标准,往往带来灾难性的和幼稚的结果(如在注释中说明)。结果
不要读。结果
咨询@Olaf,对于一个正规的,专业的解答。

DISCLAIMER
I'm an absolute beginner, 90% or more of what I have written is wrong, makes no sense, or may break you toaster. I also try to make a rationale out of the standard, often with disastrous and naive results (as stated in the comment).
Don't read.
Consult @Olaf, for a formal and professional answer.

有关的下文中,术语的建筑地​​址的由处理器(逻辑,虚拟的,直链的,物理或总线地址)所看到的设计的存储器地址。换句话说地址,你会组装使用。

For the following, the term architectural address designed a memory address as seen by the processor (logical, virtual, linear, physical or bus address). In other word the addresses that you would use in assembly.

在部分6.3.2.3。它读取

In section 6.3.2.3. it reads

值为0,或者这样一个前pression投整型常量前pression键入无效* ,被称为空指针常量
  如果空指针常数转换为指针类型,所得到的指针,称为一个空指针下,被保证比较不等
  的指针的任何对象或功能。

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. 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.

和有关整数指针转换

的整数可以被转换为任何指针类型。除previously指定的 [即。对于空指针不变的情况下]
  结果是实现定义
,可能没有正确对齐,可能不会指向一个
  所引用类型的实体,可能会重新presentation陷阱

An integer may be converted to any pointer type. Except as previously specified [i.e. for the case of null pointer constant], the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

这意味着,编译器,合规性,只需要实现从整数的函数的 int2ptr 的为指针的

These imply that the compiler, to be compliant, need only to implement a function int2ptr from integer to pointers that


  1. int2ptr(0)的是,根据定义,在空指针。结果
    注意 int2ptr(0)的未授权为0它可以重新presentation任何位。

  2. * int2ptr(N!= 0)没有限制。结果
    注意,这意味着的 int2ptr 的不必是身份的功能,也没有返回有效的指针功能!

  1. int2ptr(0) is, by definition, the null pointer.
    Note that int2ptr(0) is not mandated to be 0. It can be any bit representation.
  2. *int2ptr(n != 0) has no constraints.
    Note that this means that int2ptr needs not to be the identity function, nor a function that return valid pointers!

下面给出

char* p = (char*)241;

该标准使得绝对不能保证前pression * p = 56; 将写信给建筑地址的 241 的< BR>
,并因此它没有给出直接的方式访问任何其他建筑地址(包括 int2ptr(0)的,地址由一个空指针设计,如果有效)。

The standard makes absolute no guarantee that the expression *p = 56; will write to the architectural address 241.
And so it gives no direct way to access any other architectural address (including int2ptr(0), the address designed by a null pointer, if valid).

简而言之标准不符合建筑地址处理,但三分球,他们的比较​​,转换和他们的行动

Simply put the standard does not deal with architectural addresses, but with pointers, their comparison, conversions and their operations.

当我们写code像的char * p =(字符*)K 我们没有告诉编译器,使 P 点到建筑地址 K 的,我们告诉它做一个指针出整数的 K 的,或者以其他长期使 p 指向(C抽象)地址的 K 的。

When we write code like char* p = (char*)K we are not telling the compiler to make p point to the architectural address K, we are telling it to make a pointer out of the integer K, or in other term to make p point to the (C abstract) address K.

空指针和(建筑)地址0x0不相同的(引文中),所以是从整数作出的任何其他指针的 K 的和真实的(建筑)地址的 K

Null pointer and the (architectural) address 0x0 are not the same (cit.) and so is true for any other pointer made from the integer K and the (architectural) address K.

由于种种原因,儿时的遗产,我想用C的整数文字可以用来EX preSS建筑的地址,而不是我错了,只有恰巧是(在某种程度上)正确,我使用的编译器。

For some reasons, childhood heritages, I thought that integer literals in C could be used to express architectural addresses, instead I was wrong and that only happen to be (sort of) correct in the compilers I was using.

这个问题的答案我自己的问题很简单:有没有标准的方式,因为有C标准文件中没有(建筑)地址即可。这是真实的每一个(建筑)地址,而不是仅仅的 int2ptr(0)的有一个 1

The answer to my own question is simply: There is no standard way because there are no (architectural) address in the C standard document. This is true for every (architectural) address, not only the int2ptr(0) one1.

注意有关收益*(挥发性的char *)0;

Note about return *(volatile char*)0;

该标准说

如果一个
  无效值的 [一个空指针的值是无效值] 的已分配给指针时,目*运算符的行为是不确定的。

If an invalid value [a null pointer value is an invalid value] has been assigned to the pointer, the behavior of the unary * operator is undefined.

因此​​,任何前pression指
  这样的的 [挥发] 的对象应严格按照抽象机的规则进行评估。

Therefore any expression referring to such an [volatile] object shall be evaluated strictly according to the rules of the abstract machine.

抽象机说, * 是未定义空指针值,这样code不应该从这个区别

The abstract machine says that * is undefined for null pointer values, so that code shouldn't differ from this one

收益*(字符*)0;

这也是未定义的。结果,
事实上,他们没有什么不同后,至少在GCC 4.9,无论是编译我的问题的说明进行操作。

which is also undefined.
Indeed they don't differ, at least with GCC 4.9, both compile to the instructions stated in my question.

实现定义的方式来访问0建筑地址,对于GCC,使用的的 -fno-分离-错误的路径,解引用的标志,生产的预期集结号$ C $角

The implementation defined way to access the 0 architectural address is, for GCC, the use of the -fno-isolate-erroneous-paths-dereference flag which produces the "expected" assembly code.

<分> 的指针转换为整数或整数为指针的映射函数是为了
与执行环境的寻址结构一致。

The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment.

<分> 不幸的是它说,&安培; 生成它的操作数的地址,我认为这是一个有点不合适,我可以说,它产生一个指向它的操作数。考虑一个变量 A 是已知驻留在16位地址空间地址的的0xf1 的,并考虑一个编译器实现的 int2ptr(N )= 0x8000的| ñ的。 &放大器;一个将产生一个指向其位重新presentation是的 0x80f1 的是不会的地址 A

Unfortunately it says that the & yields the address of its operand, I believe this is a bit improper, I would say that it yields a pointer to its operand. Consider a variable a that is known to resides at address 0xf1 in a 16 bit address space and consider a compiler that implements int2ptr(n) = 0x8000 | n. &a would yield a pointer whose bit representation is 0x80f1 which is not the address of a.

<分> 1 这是我的特别需要,因为它是唯一一个,在我的实现,不能被访问。

1Which was special to me because it was the only one, in my implementations, that couldn't be accessed.

这篇关于C标准兼容的方式来访问空指针的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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