const char*
? malloc
を使用して新しいメモリを割り当てました。解放しようとすると、常に「互換性のないポインタ型」というエラーが表示されます。
これを引き起こすコードは次のようなものです:
char* name="Arnold";
const char* str=(const char*)malloc(strlen(name)+1);
free(str); // error here
数人が正しい答えを投稿しましたが、何らかの理由でそれを削除し続けています。非constポインターにキャストする必要があります。 free
はvoid*
ではなくconst void*
を取ります:
free((char*)str);
コードが逆になります。
この:
_char* name="Arnold";
const char* str=(const char*)malloc(strlen(name)+1);
_
次のようになります。
_const char* name="Arnold";
char* str=(char*)malloc(strlen(name)+1);
_
const
ストレージタイプは、割り当てられたメモリブロックを(動的または静的に)変更するつもりがないことをコンパイラに伝えます。メモリーを解放すると変更されます。注: malloc()の戻り値をキャスト する必要はありませんが、それは別です。
メモリを動的に割り当て(name
の長さに基づいて実行しています)、メモリを使用する意図がないことをコンパイラに伝えることはほとんど使用されません。 usingは、何かに書き込み、その後(オプションで)後で解放することを意味します。
別のストレージタイプにキャストしても、最初にストレージタイプを逆にしたという事実は修正されません:)何かを伝えようとしていた警告が消えるだけです。
コードが逆になっている場合(あるべき)、free()
は、実際にmodifyできるため、期待どおりに動作します割り当てられました。
Constへのポインタをmallocしても意味がありません。その内容を(いハックなしで)変更することはできないからです。
ただし、gccは次のことを警告するだけです。
//
// const.c
//
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char *p = malloc(100);
free(p);
return 0;
}
$ gcc -Wall const.c -o const
const.c: In function ‘main’:
const.c:8: warning: passing argument 1 of ‘free’ discards qualifiers from pointer target type
$
どのコンパイラを使用していますか?
const*
を解放したい場合があります。ただし、同じ関数で割り当て/割り当てを行わない限り、実行したくないでしょう。そうでなければ、物事を壊す可能性があります。実際の例については、以下のコードを参照してください。関数宣言でconst
を使用して、引数の内容を変更していないことを示しています。ただし、それはreassignedで、小文字の重複(strdup)を解放する必要があります。
char* tolowerstring(const char *to_lower)
{
char* workstring = strdup(to_lower);
for(;workstring != '\0'; workstring++)
*workstring = tolower(workstring);
return workstring;
}
int extension_checker(const char* extension, const char* to_check)
{
char* tail = tolowerstring(to_check);
extension = tolowerstring(extension);
while ( (tail = strstr( tail+1, extension)) ) { /* The +1 prevents infinite loop on multiple matches */
if ( (*extension != '.' ) && ( tail[-1] != '.'))
continue;
if ( tail[strlen(extension)] == '\0') {
free(tail);
free( (char*) extension);
return 1;
}
}
free(tail);
free( (char *) extension);
return 0;
}
Constにmallocされたポインターをキャストすることは目的がありません。 constポインターを受け取る関数は、渡されたメモリを解放する責任を負わないようにする必要があります。
いくつかの答えは、単に_char*
_にキャストすることを示唆しています。しかし、el.pescadoが上記に書いたように、
const
をconst
以外にキャストすることは、コード臭の兆候です。
Gccの_-Wcast-qual
_など、これを防ぐコンパイラ警告がありますが、これは非常に便利です。 本当にがconst
ポインタを解放するための有効なケースを持っている場合(多くの人がここに書いたものとは反対に、そこにare nlstdによって指摘された有効なケースがあります) )、そのために次のようなマクロを定義できます。
_#define free_const(x) free((void*)(long)(x))
_
これは少なくともgccで機能します。二重キャストにより、ロジック_-Wcast-qual
_はこれを「キャストconst離れ」として検出しません。言うまでもなく、このマクロは注意して使用する必要があります。実際には、同じ関数で割り当てられたポインターにのみ使用する必要があります。
私は間違っているかもしれませんが、問題はconst
にあると思います。ポインタを次のように非constにキャストします。
free((char *) p);
const
で言うのは:このポインターが指すデータを変更しないでください。
純粋なCについて話していて、メモリ割り当てを完全に制御している場合は、次のトリックを使用して(const char *)を(char *)にキャストできます。これにより、コンパイラで警告が表示されません。
const char *const_str = (const char *)malloc(...);
char *str = NULL;
union {
char *mutable_field_p;
const char *const_field_p;
} u;
u.const_field_p = const_str;
str = u.mutable_field_p;
これでfree(str)を使用できます。メモリを解放します。
しかし、これは言葉を超えた悪であり、厳密に制御された環境でのみ使用する必要があることに注意してください(たとえば、文字列を割り当てて解放しますが、ユーザーが文字列を変更することを望まないライブラリ)コンパイル時間「STRING」を無料の関数に追加します。
本当の答えは、freeはconst
ポインター引数を取り、NULL
はconst
ポインターとして定義されるべきだと思います。これは標準のバグのようです。 const
ポインターの解放は、次のように実装する必要があります。
free(p);
p = NULL;
この場合、コンパイラがどのように誤ったコードを生成するかわかりません。const
ポインターp
にはアクセスできなくなります。したがって、ポインターが指しているオブジェクトがconst
、有効、その他何でも。そのconst
は、レジスターまたはその他の場所にダーティーコピーが存在しないようにします。 const
ポインターを別の値に設定することは有効であり、その値がNULL
であるという事実は、以前の値にアクセスできなくなったため重要ではありません。
const
であるため、const char *
を解放できません。 malloc
から受け取ったポインターを非constポインター変数に格納し、free
に渡すことができるようにします。 char *
引数を受け取る関数にconst char *
引数を渡すことができますが、逆は常に真とは限りません。
void foo (const char *x);
char *ptr = malloc (...);
foo (ptr);
free (ptr);