【问题标题】:pointer to pointer malloc and manipulation指向指针 malloc 的指针和操作
【发布时间】:2011-06-17 09:35:51
【问题描述】:
#include <stdio.h>
#include <stdlib.h>


int main(int argc, char * argv[])
{
    char *p[2];
    char **pp = calloc(2, 4);

    p[0] = "ab";
    p[1] = "cd";
//  p[2] = "ef";

    pp[0] = "ab";
    pp[1] = "cd";
    pp[2] = "ef";

    printf("pp: %s, %s, %s\n", pp[0], pp[1], pp[2]);
    printf("size_p: %d\nsize_pp: %d\n", sizeof p, sizeof pp);
}

如果 'p[2]' 被定义并分配了一个值 - 结果行为是一个段错误。如果分配了 'pp[2]' - 输出如下:“ab, cd, ef”。 'sizeof' 为 'p' 返回 8(每个指针 2x4 字节),而为 'pp' 仅返回 4 个字节。为什么我能够分配'pp [2]',即使它应该只拥有8字节的分配内存(应该只能存储2个指针地址)?另外,'sizeof' 如何确定这两种情况下的实际内存大小?

【问题讨论】:

  • 你在哪个平台/操作系统上运行这个程序?你用什么libc?
  • @levu Ubuntu,x86_64 GNU/Linux,glibc '2.7-10ubuntu7'

标签: c pointers malloc


【解决方案1】:

p 被声明为有两个元素,所以 p[2] 不存在 - 因此是段错误。由于p 是一个局部数组(指针),sizeof(p) 给出了元素类型的大小(元素类型为char *,其大小为4)乘以元素的数量(2)。另一方面,pp 是一个指针(指向一个指针),而不是一个数组,所以 sizeof(p) 只是 char ** 的大小,它与 32 上任何其他指针的大小相同-bit 机器,即 4。分配给 pp[2] 似乎成功纯属机会 - 您在分配的内存之外写入(仅包含两个 char * 元素的空间)。

顺便说一下,指向字符串字面量的指针应该是const char *

【讨论】:

    【解决方案2】:

    使用char *p[2];,您在堆栈上分配了2 个char*。在访问p[2] 时,您会遇到缓冲区溢出,并且可能会访问属于当前方法的堆栈帧的任何其他 fing(一些编译器会在调试模式下检查这一点)。

    使用calloc,您可以在堆中分配内存。访问pp[2] 是(可能)空闲内存,这里没有段错误。但是这块内存也可能被其他对象使用,所以这绝对不行!

    对于大小计算:sizeof(char**) 是 4,对于每个 32 位指针也是如此。 sizeof(char*[2]) 是 8,因为它是 2x4 字节。

    【讨论】:

    • 这似乎是最好的答案,因为它涵盖了内存分配的技术方面。谢谢。
    【解决方案3】:

    正如 Aasmund Eldhuset 所说,p[2] 不存在。 p[0] 和 p[1] 是数组的两个元素。

    据我了解,它为 p[2] 而不是 pp[2] 出现段错误的原因是,因为 p 存储在堆栈中,而 pp 存储在堆中。因此,尽管您不拥有 pp[2] 处的内存,但它不会出现段错误。相反,它只是覆盖了上帝知道的内容,并且可能会导致您的程序以不可预知的方式行为异常。

    一般来说,如果您超出其界限,动态分配的内存(例如您的示例中的 pp)不会总是出现段错误,而静态分配的内存(例如 p)会出现段错误。

    【讨论】:

    • 我不知道为什么人们不断重复有关 p[2] 的段错误的事情 :) 我从来没有问过为什么会发生这种情况,因为这很明显。感谢您对 king_nak 帖子的另一部分稍加详尽的补充。
    猜你喜欢
    • 1970-01-01
    • 2017-05-13
    • 2012-08-17
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多