0

给定以下代码:

RTIME *rtCreate(void)
{
    RTIME *rtime;

    rtime = malloc(sizeof(*rtime));

    if (rtime != NULL)
    {
        /* Initialization stuff */
    }

    return rtime;
}

void rtDestroy(RTIME **rtime)
{
    if (*rtime != NULL)
    {
        free(*rtime);
        *rtime = NULL;
    }
}

什么会导致 GCC 抱怨“传递 'free' 的参数 1 会丢弃指针目标类型的限定符”?我知道没有必要强制转换 malloc 的结果(如此处所讨论),因为指向 void 的指针会自动转换为正确的类型。那么为什么编译器似乎暗示我必须*rtime在它被释放之前强制转换?

编辑:- RTIME 定义如下。

typedef struct RTIME
{
    uint8 Sec;
    uint8 Min;
    uint8 Hour;
    uint8 DayOfWeek;
    uint8 DayOfMonth;
    uint16 DayOfYear;
    uint8 Month;
    uint16 Year;
} volatile RTIME;
4

3 回答 3

1

获取您的代码并从中制作SSCCE,如下所示:

#include <stdlib.h>

struct RTIME { int a; int b; };
typedef const struct RTIME RTIME;

RTIME *rtCreate(void)
{
    RTIME *rtime;

    rtime = malloc(sizeof(*rtime));

    if (rtime != NULL)
    {
        /* Initialization stuff */
    }

    return rtime;
}

void rtDestroy(RTIME **rtime)
{
    if (*rtime != NULL)
    {
        free(*rtime);
        *rtime = NULL;
    }
}

使用 GCC 4.7.1 和命令行编译:

$ gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -c mf.c
mf.c:6:8: warning: no previous prototype for ‘rtCreate’ [-Wmissing-prototypes]
mf.c:20:6: warning: no previous prototype for ‘rtDestroy’ [-Wmissing-prototypes]
mf.c: In function ‘rtDestroy’:
mf.c:24:9: warning: passing argument 1 of ‘free’ discards ‘const’ qualifier from pointer target type [enabled by default]
In file included from mf.c:1:0:
/usr/include/stdlib.h:160:7: note: expected ‘void *’ but argument is of type ‘const struct RTIME *’
$

省略const并且您只会收到有关缺少原型的(有效)警告。

我猜你正在使用旧版本的 GCC(因为旧版本不包含该note:行中的额外信息),并且不知何故你的typedefforRTIME包含一个const.

作为一般规则,您不需要consta typedef,但该规则肯定会有例外。


从编辑过的问题中可以看出,限定词是volatile而不是const. 当typedef我的示例代码更改时,GCC 4.7.1 说:

mf.c:6:8: warning: no previous prototype for ‘rtCreate’ [-Wmissing-prototypes]
mf.c:20:6: warning: no previous prototype for ‘rtDestroy’ [-Wmissing-prototypes]
mf.c: In function ‘rtDestroy’:
mf.c:24:9: warning: passing argument 1 of ‘free’ discards ‘volatile’ qualifier from pointer target type [enabled by default]
In file included from mf.c:1:0:
/usr/include/stdlib.h:160:7: note: expected ‘void *’ but argument is of type ‘volatile struct RTIME *’

当我使用系统 GCC 编译时,我得到一个更简单、不太精确的错误消息:

mf.c:7: warning: no previous prototype for ‘rtCreate’
mf.c:21: warning: no previous prototype for ‘rtDestroy’
mf.c: In function ‘rtDestroy’:
mf.c:24: warning: passing argument 1 of ‘free’ discards qualifiers from pointer target type

这是来自 Apple 的 GCC:

i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)

因此,限定词是volatile而不是const.


尝试升级到 GCC 4.7.x 的一个很好的理由是错误消息比早期版本有了很大改进。改进的消息也在 4.6.0 中;4.5.2 中的消息是较旧的样式,信息量较少的消息。

于 2013-01-04T02:45:30.950 回答
0

问题在于volatile属性 - freegets void *,它不是易失性的,因此您不能将RTIME(易失性)传递给它。

您应该问自己为什么要使用volatile。这个限定词经常被误解。
在我见过的许多情况下,volatile它要么用于解决不存在的问题,要么用于解决即使您使用它仍然存在的问题(最常见的是竞争条件)。

于 2013-01-04T06:51:44.377 回答
0

我建议你重写你的rtDestroy()函数如下。似乎 GCC 看到了指向指针的指针的取消引用,并将其视为可能的错误来源。

您似乎想要释放分配的内存,然后将指针设置为 NULL,以便轻松检测指针不再有效。但是,通过执行您正在执行的操作,该free()函数将通过编译器无法检查的重定向获得要释放的内存地址。

因此,如果您将 *rtime 指向的地址分配给局部变量,然后将其传递给 free() 函数,编译器检查应该通过。对于某些类型的源构造,这似乎是一个相当常见的警告。当变量需要 const 修饰符并且未指定时,这似乎是最常见的。请参阅此示例Initialization 从指针目标类型中丢弃限定符

void rtDestroy(RTIME **rtime)
{
    RTIME *pTemp = *rtime;

    if (*rtime != NULL)
    {
        free(pTemp);
        *rtime = NULL;
    }
}

编辑: 似乎 RTIME 是一种变量类型,包含以纳秒为单位的硬件时间滴答或类似的东西。除非使用的函数提供指向只读操作系统内存区域的指针,否则不确定为什么它会是 const。

我建议没有真正需要分配内存,而是使用堆栈上的变量并使用适当的函数来检索无论如何都会改变的当前值。

RTIME *pTemp = *rtime;但是,如果 RTIME 涉及 const,那么您可以尝试使用而不是使用,void *pTemp = (void *) (*rtime);那么我希望这只会将警告放在该行上。Jonathan Leffler(见下面的评论)报告说,他发现我上面建议的更改存在相同的错误。

请参阅这篇文章实时 Linux II

于 2013-01-04T02:45:01.827 回答