在C中,为什么有些人在释放之前会抛出指针?

时间:2015-12-01 12:01:29

标签: c pointers casting

我正在处理旧的代码库,而且几乎每次调用free()都会在其参数上使用强制转换。例如,

free((float *)velocity);
free((float *)acceleration);
free((char *)label);

其中每个指针都是相应的(和匹配的)类型。我完全没有理由这样做。这是一个非常古老的代码,所以我想知道它是不是K& R的东西。如果是这样,我实际上希望支持可能需要这个的旧编译器,所以我不想删除它们。

是否有使用这些演员表的技术理由?我甚至没有看到使用它们的实用理由。在释放数据类型之前提醒自己的重点是什么?

编辑:此问题是另一个问题的副本。另一个问题是这个问题的一个特例,如果亲密选民能够阅读所有答案,我认为这是显而易见的。

Colophon:我正在给出" const答案"选中标记,因为这可能是为什么需要这样做的真正原因;然而,关于它是一个ANSI C之前的习惯(至少在一些程序员中)的答案似乎是它在我的情况下使用的原因。很多人在这里有很多好处。感谢您的贡献。

6 个答案:

答案 0 :(得分:168)

如果指针为const,则可能需要强制转换才能解析编译器警告。下面是一个代码示例,该代码在不转换free参数的情况下导致警告:

const float* velocity = malloc(2*sizeof(float));
free(velocity);

编译器(gcc 4.8.3)说:

main.c: In function ‘main’:
main.c:9:5: warning: passing argument 1 of ‘free’ discards ‘const’ qualifier from pointer target type [enabled by default]
     free(velocity);
     ^
In file included from main.c:2:0:
/usr/include/stdlib.h:482:13: note: expected ‘void *’ but argument is of type ‘const float *’
 extern void free (void *__ptr) __THROW;

如果使用free((float*) velocity);,编译器会停止抱怨。

答案 1 :(得分:60)

预标准C没有void*但只有char*,因此您必须投射所有传递的参数。如果你遇到古老的C代码,你可能会发现这样的演员阵容。

Similar question with references

当第一个C标准发布时,malloc和free的原型从char*变为今天仍然拥有的void*

当然,在标准C中,这样的演员表是多余的,只是危害可读性。

答案 2 :(得分:33)

这是一个免费在没有演员表的情况下失败的例子:

volatile int* p = (volatile int*)malloc(5 * sizeof(int));
free(p);        // fail: warning C4090: 'function' : different 'volatile' qualifiers
free((int*)p);  // success :)
free((void*)p); // success :)

在C中,您可以收到警告(在VS2012中获得警告)。在C ++中,你会收到一个错误。

除了罕见的情况外,演员阵容只会使代码膨胀......

修改 我转而void*而非int*来演示失败。它将与int*隐含地转换为void*的工作方式相同。添加了int*代码。

答案 3 :(得分:30)

原因:1。通过使用<audio>,代码明确指出应将指针视为play()调用的一部分的类型。当free((sometype*) ptr)替换为(自己动手)free()时,显式强制转换非常有用。

free()

DIY_free()是一种方法,特别是在调试模式下,对被释放的指针进行运行时分析。这通常与#define free(ptr) DIY_free(ptr, sizeof (*ptr)) 配对以添加声望,全局内存使用计数等。我的小组在出现更多现代工具之前使用了这种技术多年。它必须将自由项目转换为最初分配的类型。

  1. 鉴于花了很多时间来追踪内存问题等,像免费使用类型这样的小技巧会有助于搜索和缩小调试范围。
  2. 现代:避免Manos Nikolaidis@@egur处理的DIY_free()DIY_malloc()警告。我想我会注意到3个限定符的效果:constvolatileconst

    [edit]每@R.. comment

    添加了volatile
    restrict

答案 4 :(得分:16)

这是另一种替代假设。

我们被告知该程序是在C89之前编写的,这意味着它无法解决与free原型的某种不匹配问题,因为不仅没有const这样的事情。在C89之前{1}}也不是void *,在C89之前没有函数原型这样的东西。 stdlib.h本身就是委员会的一项发明。如果系统标题根本无法声明free,那么他们就会这样做:

extern free();  /* no `void` return type either! */

现在,关键在于缺少函数原型意味着编译器没有参数类型检查。它应用了默认参数提升(仍然适用于可变参数函数调用的那些),就是这样。使每个呼叫站点的参数与被呼叫者的期望一致的责任与程序员完​​全。

然而,这仍然并不意味着必须在大多数K&amp; R编译器上将参数转换为free。像

这样的函数
free_stuff(a, b, c)
    float *a;
    char *b;
    int *c;
{
    free(a);
    free(b);
    free(c);
}

应该已经正确编译。所以我认为我们在这里得到的是一个程序,用于处理异常环境中的错误编译器:例如,sizeof(float *) > sizeof(int)和编译器不会对指针使用适当的调用约定,除非你在调用点转换它们。

我不知道有这样的环境,但这并不意味着没有这样的环境。想到的最可能的候选人被削减&#34;小C&#34; 20世纪80年代早期的8位和16位微处理器编译器。我也不会惊讶地发现早期的Crays有这样的问题。

答案 5 :(得分:9)

free只接受非const指针作为参数。因此,在const指针的情况下,需要显式转换为非const指针。

Unable to free const pointers in C