使用malloc,如何分配没有分配的内存? [英] Memory allocated without allocation using malloc, how?

查看:108
本文介绍了使用malloc,如何分配没有分配的内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是一个简单的code片断:

Below is a simple code snippet:

int main()
{
int *p;
p=(int*)malloc(sizeof(int));//allocate m/y 4 1 int 
printf("P=%p\tQ=%p",p,p+2);
}

在一个样本来看,它给我的输出如下:

In one sample run, it gave me the output as below:

P=0x8210008 Q=0x8210010

磷起始地址-P = 0x8210008,下一个字节是0x8210009,下一个字节是0x821000A,下一个字节是0x821000B.So为INT 4个字节没有结束。
使用malloc我们还没有分配更多的内存。
那么如何为p + 2引领我们0x8210010,这为P后的8个字节(0x8210008)。

Starting address of P is-P=0x8210008,next byte is 0x8210009,next byte is 0x821000A,next byte is 0x821000B.So the 4 bytes for int is ending there. We haven't allocated more memory using malloc. Then how is p+2 leading us to 0x8210010,which is 8 bytes after P(0x8210008).

推荐答案

首先,你已经打印的地址并不意味着内存的事实,在该地址被分配。您只是添加号码,并生产其他号码。

First, the fact that you have printed an address does not imply that memory is allocated at that address. You have simply added numbers and produced other numbers.

二,你号码,您通过添加两个得到的原因是比基地址,而不是两个比基地址大是因为,当您添加整数在C指针,算术是尖头方面做了8更大-to元素,而不是在内存字节为单位(除非指向的元素是字节)。假设你有一个int数组,说 INT X [8] ,和你有一个指针 X [3] 。添加两到该指针产生一个指向 X [5] ,而不是指向两个字节超越开始X [3] 。重要的是要记住,C是一种抽象,和C标准规定,抽象内部发生了什么是很重要的。内部的C抽象,指针运算上的元素,而不是原始内存地址的号码。 C实现(编译器和转C $ C $ç进入执行程序的工具)需要执行原料内存地址的任何操作来实现由C标准规定的抽象是必需的。通常情况下,这意味着,编译器通过将其加入到一个指针,当元件的尺寸乘以一个整数。于是两个乘以4(一台机器,其中一个 INT 是四个字节),并导致被加到基地址的八个

Second, the reason that you number you got by adding two was eight greater than the base address instead of two greater than the base address was because, when you add integers to pointers in C, the arithmetic is done in terms of pointed-to elements, not in terms of bytes in memory (unless the pointed-to elements are bytes). Suppose you have an array of int, say int x[8], and you have a pointer to x[3]. Adding two to that pointer produces a pointer to x[5], not a pointer to two bytes beyond the start of x[3]. It is important to remember that C is an abstraction, and the C standard specifies what happens inside that abstraction. Inside the C abstraction, pointer arithmetic works on numbers of elements, not on raw memory addresses. The C implementation (the compiler and the tools that turn C code into program execution) is required to perform whatever operations on raw memory addresses are required to implement the abstraction specified by the C standard. Typically, that means the compiler multiplies an integer by the size of an element when adding it to a pointer. So two is multiplied by four (on a machine where an int is four bytes), and the eight that results is added to the base address.

第三,你不能依赖此行为。 C标准定义指针算法只为指向对象数组里面的指针,包括在阵列底端的一个虚构的对象。此外,指针单个对象像一种元素的阵列。所以,如果你有一个指针 P 它指向一个int,你被允许计算 P + 0 p + 1 ,因为它们指向的唯一对象数组中( p + 0 )和虚拟物体一举超越数组中的最后一个元素( p + 1 )。您的不可以允许计算 P-1 P + 2 ,因为这些都是阵列之外。请注意,这不是取消引用指针(试图在计算地址读取或写入存储器)的问题:即使只是计算地址结果的行为不是由C标准定义的:您的程序可能崩溃,它可以给你正确的结果,也可以删除帐户中的所有文件,所有这些行为将符合C标准。

Third, you cannot rely on this behavior. The C standard defines pointer arithmetic only for pointers that point to objects inside arrays, including one fictitious object at the end of the array. Additionally, pointers to individual objects act like arrays of one element. So, if you have a pointer p that points to an int, you are allowed to calculate p+0 or p+1, because they point to the only object in the array (p+0) and the fictitious object one beyond the last element in the array (p+1). You are not allowed to calculate p-1 or p+2, because these are outside the array. Note that this is not a matter of dereferencing the pointer (attempting to read or write memory at the calculated address): Even merely calculating the address results in behavior that is not defined by the C standard: Your program could crash, it could give you "correct" results, or it could delete all files in your account, and all of those behaviors would be conforming to the C standard.

这是不可能的,仅仅计算一个彻头彻尾的越界地址会产生这样怪异的行为。然而,标准允许的话,因为有些计算机处理器有需要比简单的算术更多的工作不寻常的地址方案。或许平面地址空间后,第二最常见的地址方案是一个基地址和偏移方案。在这样的方案中,一个四字节指针的高位16位中可能包含一个基地址,低16位可能包含的偏移。对于给定的基址B和偏移0,对应的虚拟地址可能是4096 * B + O。 (这样的方案是能够寻址的仅2 20 字节,和碱的许多不同的值和偏移可以参考相同的地址。例如,基0和偏移4096指的是​​相同的地址基1和偏移0)与一种碱和 - 偏置方案中,编译器可能通过只增加了偏移和忽略碱实现指针运算。 (这样的C实现可以支持阵列仅达65536个字节,由偏移单独的程度可寻址的。)在这样的实施方式中,如果有指针到INT P 与0x0000fffc的编码(基数为0,偏移65532),和 INT 是四个字节,那么 p + 2 将具有值0x00000004,而不是说为八大于(0x00010004)。

It is unlikely that merely calculating an out-of-bounds address would produce such weird behavior. However, the standard permits it because some computer processors have unusual address schemes that require more work than simple arithmetic. Perhaps the second-most common address scheme after the flat address space is a base address and offset scheme. In such a scheme, the high 16 bits of a four-byte pointer might contain a base address, and the low 16 bits might contain an offset. For a given base address b and offset o, the corresponding virtual address might be 4096*b+o. (Such a scheme is capable of addressing only 220 bytes, and many different values of base and offset can refer to the same address. For example, base 0 and offset 4096 refer to the same address as base 1 and offset 0.) With a base-and-offset scheme, the compiler might implement pointer arithmetic by adding only to the offset and ignoring the base. (Such a C implementation can support arrays only up to 65536 bytes, the extent addressable by the offset alone.) In such an implementation, if you have pointer-to-int p with an encoding of 0x0000fffc (base 0, offset 65532), and int is four bytes, then p+2 will have the value 0x00000004, not the value that is eight greater (0x00010004).

这就是指针运算产生,你会不会从一台机器的地址值期待一个例子。这是很难想象的地方指针运算,根据C标准会产生碰撞是无效的实现。但是,考虑其中存储器必须由一个过程可以手动换一种实现中,因为处理器不必支持虚拟存储器硬件。在这样的实施中,指针可能包含在存储器描述磁盘位置和用于管理存储器交换的其它信息的结构的地址。在这样的实施,做指针运算,可能需要阅读结构在内存中,这样做无效指针运算可能读书无效的地址。

That is an example where pointer arithmetic produces values that you would not expect from a flat-address machine. It is harder to imagine an implementation where pointer arithmetic that is not valid according to the C standard would produce a crash. However, consider an implementation in which memory must be manually swapped by a process, because the processor does not have the hardware to support virtual memory. In such an implementation, pointers might contain addresses of structures in memory that describe disk locations and other information used to manage the memory swapping. In such an implementation, doing pointer arithmetic might require reading the structures in memory, and so doing invalid pointer arithmetic might reading invalid addresses.

这篇关于使用malloc,如何分配没有分配的内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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