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を渡すと、ポインターターゲット型から修飾子が破棄される」と文句を言う原因は何でしょうか。voidへのポインタが自動的に正しい型に変換されるため、mallocの結果をキャストする必要がないことを理解しました(ここで説明します)。それでは、なぜコンパイラーは、*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:行に追加情報が含まれていないため)、何らかの形でtypedefforRTIMEconst.

原則として、 は必要ありませんconsttypedef、ルールには例外があります。


編集された質問から、修飾子が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 へのアップグレードを試みる正当な理由の 1 つは、以前のバージョンよりもエラー メッセージが大幅に改善されていることです。改善されたメッセージは 4.6.0 にもあります。4.5.2 のメッセージは古いスタイルで、情報量の少ないメッセージでした。

于 2013-01-04T02:45:30.950 に答える
0

問題はvolatile属性freeにありますvoid *-getsは揮発性ではないため、(揮発性である)属性に渡すことはできませんRTIME

なぜ使用volatileしているのかを自問する必要があります。この修飾子はよく誤解されます。
多くの場合、私が見たのvolatileは、存在しない問題、またはそれを使用してもまだ存在する問題(ほとんどの場合、競合状態)を解決するために使用されます。

于 2013-01-04T06:51:44.377 に答える
0

rtDestroy()関数を次のように書き直すことをお勧めします。GCC がポインタへのポインタの逆参照を認識しているようで、それをエラーの原因と見なしています。

ポインターが無効になったことを簡単に検出するために、割り当てられたメモリを解放し、ポインターを NULL に設定したいと考えているようです。ただし、あなたがしていることを行うことfree()で、コンパイラがチェックできないリダイレクトを通じて解放するメモリのアドレスが関数に与えられます。

したがって、*rtime が指すアドレスをローカル変数に割り当て、それを free() 関数に渡すと、コンパイラ チェックはパスするはずです。これは、一部のタイプのソース構成でかなり一般的な警告のようです。変数に const 修飾子が必要で、指定されていない場合に最も一般的なようです。この例を参照してください。初期化により、ポインタ ターゲット タイプから修飾子が破棄されます

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

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

編集: RTIME は、ナノ秒単位のハードウェア タイム ティックなどを含む変数型のようです。使用される関数が読み取り専用のオペレーティング システム メモリ領域へのポインタを提供しない限り、なぜ const になるのかわかりません。

代わりに、スタック上の変数を使用し、適切な関数を使用して、とにかく変化する現在の値を取得するメモリの割り当てを行う必要はないことをお勧めします。

ただし、使用するのではなく使用RTIME *pTemp = *rtime;することもできますがvoid *pTemp = (void *) (*rtime);、RTIME に const が含まれている場合は、代わりにその行に警告が表示されると思います。Jonathan Leffler (以下のコメントを参照) は、私が上で提案した変更で同じエラーが発生したと報告しています。

この記事 Real Time Linux IIを参照してください。

于 2013-01-04T02:45:01.827 に答える