【问题标题】:Using free to deallocate a non char pointer in C在 C 中使用 free 释放非 char 指针
【发布时间】:2017-09-07 16:05:17
【问题描述】:

在阅读此article 时,我看到了这段:

指向对象的指针可能大小相同但格式不同。这 如下代码所示:

int *p = (int *) malloc(...); ... free(p);

此代码可能在 int * 和 char * 具有 不同的表示,因为 free 需要后者的指针 输入。

这不是我第一次读到free 需要char* 类型。

我的问题是,如何释放p

【问题讨论】:

  • free 采用 void *,而不是 char *。获取最近(即不超过 18 岁且关于现代 C)的书。这也将解释语义,而不是投射malloc 和朋友的结果。
  • 但是 free 期望 void * 作为参数。您链接到的文章是非常旧的。此外,您找到不同指针类型具有不同表示的系统的可能性微乎其微(除非您想专攻古代系统和计算机考古学)
  • @Someprogrammerdude 即使文章很旧,作者也知道标准 C。所以我猜该段落是错误的而不是旧的。
  • @BiteBytes 但是 C 直到 1989 年 (ANSI) 和 1990 年 (ISO) 才真正标准化,所以到本文最初撰写时,可能已经有大量可用的预标准编译器。今天,唯一不符合现代标准的广泛使用的 C 编译器是 Microsoft Visual Studio C 编译器(尽管它仍然完全兼容 C89/90)。
  • 嗯,它关于可移植性的,当时并非所有编译器都符合标准,这可能是你引用的原因。因此,为了便于移植(当时),不能假设 free 函数采用了 void * 参数(或者 malloc 返回了 void *)。

标签: c pointers malloc free


【解决方案1】:

注意You should not cast the return value of malloc in C.

这个问题说明了读取潜在无效资源的危险。确保您阅读的资源准确无误是极其重要!有问题的 OPs 资源在其时代并没有错,但是已经过时了,因此无效。具有讽刺意味的是,K&R 2E 早了一岁,但仍然非常过时(因此仍然强烈推荐),因为它遵循标准。

如果我们咨询a more reputable resource (the free manual),我们可以看到free实际上期望指针是void *类型:

void free(void *ptr);

...不管它的价值,here's the malloc manual showing that malloc returns void *:

void *malloc(size_t size);

在这两种情况下,如C11/6.3.2.3p1(C11 标准)所述:

指向 void 的指针可以转换为指向任何对象类型的指针或从指向任何对象类型的指针转​​换。指向任何对象类型的指针都可以转换为指向 void 的指针并再次返回;结果应与原始指针比较。

int *p = malloc(...); // A conversion occurs here; `void *` as returned by malloc is converted to `int *`
free(p);              // ... and the reverse of the conversion occurs here, to complete the cycle mentioned in C11/6.3.2.3p1

注意(以防您第一次错过):You should not cast the return value of malloc in C。毕竟传给free的时候就不用投了吧?

【讨论】:

  • 我已经研究过 K&R,并且我知道 free 需要 void*,我只是想通过询问 SO 来确保文档不准确。
  • 摘自我引用的文章:“除了下一节提到的 void * 类型外,标准还引入了 long double 类型。”。如您所见,他们知道 void*Standard。所以这不是变老的问题。
  • 好吧,现在你知道了......就像我的一些问题具有类似的“我需要验证”性质,我认为这个问题将(错误地)关闭,然后删除。什么时候告诉我,因为这个问题应该保留。是的,这篇文章提到了标准和 K&R2E,但仍然坚持在这些资源之前的可移植性是必要的......在那些日子里是这样,但现在不是,特别是对于“类 Unix 操作系统”(POSIX/Open组定义)。
  • 我要指出的是资源没有错误;事实上,从历史的角度来看,考虑到 C89 之前的C 的历史定义,甚至在 C89 和 C99 之间的过渡期间,对于仍然使用旧的 C89 之前的编译器的任何系统,这份文件有一些真相。现在你很难找到这样的编译器,所以这不是问题......对于任何 C89、C99 或 C11 实现这是错误的。它无效是因为它可能是错的,而不是因为它总是错的(因为毕竟有时它是对的)。
猜你喜欢
  • 2011-10-28
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-18
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多