5

我正在使用 malloc 编写代码,然后遇到了一个问题,所以我编写了一个测试代码,它实际上总结了整个混乱,如下所示:

# include <stdio.h>
# include <stdlib.h>
# include <error.h>

int main()     
{
     int *p = NULL;
     void *t = NULL;
     unsigned short *d = NULL;

     t = malloc(2);
     if(t == NULL) perror("\n ERROR:");
     printf("\nSHORT:%d\n",sizeof(short));
     d =t;
     (*d) = 65536;
     p = t; 
     *p = 65536;
     printf("\nP:%p: D:%p:\n",p,d);
     printf("\nVAL_P:%d ## VAL_D:%d\n",(*p),(*d));
     return 0;
  }
   Output:: abhi@ubuntu:~/Desktop/ad/A1/CC$ ./test

            SHORT:2
            P:0x9512008: D:0x9512008:
            VAL_P:65536 ## VAL_D:0

我正在使用 malloc 分配2 个字节的内存。返回 void * 指针的 Malloc存储在 void* 指针 't'中。

然后在这 2 个指针被声明为p-整数类型和 d-短类型。然后我将 t 分配给它们* (p = t 和 d = t) * ,这意味着 d 和 p 都指向堆上的相同内存位置。

在尝试将 65536(2^16) 保存到 (*d) 时,我收到警告说大 int 值被截断,这是预期的。现在我再次将 65536(2^16) 保存到 (*p) 没有引起任何警告。

*在打印 (*p) 和 ( d) 时,我得到了不同的值(尽管每个值都对自己定义的指针类型正确)。

我的问题是:

  1. 虽然我已经使用 malloc 分配了 2 个字节(即 16 位)的堆内存,但我如何能够在这两个字节中保存 65536(通过使用(p),它是一个整数类型的指针)。??我有一种感觉,这是因为将 void 自动类型转换为 int* 指针(在 p = t 中),因此将 t 分配给 p 会导致访问通过 malloc 分配的内存区域之外的内存区域。???。

  2. 即使所有这一切都在发生,地狱如何通过 (*p) 和 (*d) 取消引用同一内存区域会打印两个不同的答案(尽管如果我在想问题 1 中的原因,这也可以解释)。

有人可以对此有所了解,这将非常感激..如果有人可以解释这背后的原因..

非常感谢

4

3 回答 3

2

先回答你的第二个问题:

解释是anint一般是4个字节,最重要的字节可能存放在前两个位置。Ashort只有 2 个字节,它的数据也存储在前两个位置。显然,存储65536在 anint和 ashort中,但指向相同的内存位置,将导致存储的数据相对于 偏移两个字节intshort其中两个最低有效字节int对应于存储的short.

因此,当编译器打印 时*d,它会将其解释为 ashort并查看与存储对应的区域 a short,这不是编译器先前存储写入65536时间的位置。*p请注意,写入会*p = 65536;覆盖前一个*d = 65536;,用 . 填充两个最低有效字节0

关于第一个问题:编译器不会65536for存储*p在 2 个字节内。它只是超出了您分配的内存范围 - 这可能会在某些时候导致错误。

于 2012-04-21T19:34:47.513 回答
1

在 C 语言中,对于超出分配范围的写入根本没有保护。只是不要这样做,任何事情都可能发生。在这里它似乎对您有用,因为巧合的是,您分配的两个字节后面的空间没有用于其他用途。

于 2012-04-21T19:27:13.683 回答
0

1)OS内存管理器的粒度为4K。一位的覆盖不太可能触发 AV/segfault,但它会破坏相邻位置的任何数据,导致:

2) 未定义的行为。这组行为包括“明显正确的操作”,(现在!)。

于 2012-04-21T19:33:54.090 回答