C 言語でのフリーの無効なポインタエラーの修正
胡金庫
2023年10月12日
この記事では、C 言語で free
の無効なポインタエラーを修正する方法について、複数の方法を紹介します。
非動的メモリ位置を指す free
ポインタではありません
free
関数呼び出しは、malloc
、calloc
、realloc
関数が返したポインタからメモリを解放するためにのみ使用されるべきです。以下のコードは、char*
ポインタに malloc
コールから返された値を代入したが、後に else
ブロックの中で同じポインタに文字列リテラルが代入されてしまうというシナリオを示しています。これは、c_str
変数が動的メモリ領域ではない場所を指していることを意味し、free
関数に渡すことはできません。その結果、次の例を実行して free
関数の呼び出しに到達すると、プログラムは中断され、free(): invalid pointer
エラーが表示されます。
元の場所を指している他のポインタ変数が存在しない限り、異なるアドレスを持つ動的メモリの場所へのポインタを再割り当てしてはならないことに注意してください。最後に、ヒープメモリを指すポインタに対してのみ free
関数を呼び出すべきです。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[]) {
char *c_str = NULL;
size_t len;
if (argc != 2) {
printf("Usage: ./program string\n");
exit(EXIT_FAILURE);
}
if ((len = strlen(argv[1])) >= 4) {
c_str = (char *)malloc(len);
if (!c_str) {
perror("malloc");
}
strcpy(c_str, argv[1]);
printf("%s\n", c_str);
} else {
c_str = "Some Literal String";
printf("%s\n", c_str);
}
free(c_str);
exit(EXIT_SUCCESS);
}
既に解放されているポインタを free
しない
ダイナミックメモリを使用する際のもう一つの一般的なエラーは、既に解放されているポインタに対して free
関数を呼び出すことです。このシナリオは、同じダイナミックメモリ領域を指す複数のポインタ変数がある場合に起こりやすいです。以下のサンプルコードは、同じ場所が異なるスコープで解放される、そのようなケースを示しています。
この例は単一ファイルのショートプログラムであり、このような問題を診断するのは簡単ですが、大規模なコードベースでは、静的解析を行う外部のインスペクタプログラムがないと、ソースを追跡するのが難しいことに気づくかもしれません。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[]) {
char *c_str = NULL;
size_t len;
if (argc != 2) {
printf("Usage: ./program string\n");
exit(EXIT_FAILURE);
}
char *s = NULL;
if ((len = strlen(argv[1])) >= 4) {
c_str = (char *)malloc(len);
s = c_str;
if (!c_str) {
perror("malloc");
}
strcpy(c_str, argv[1]);
printf("%s\n", c_str);
free(c_str);
} else {
c_str = "Some Literal String";
printf("%s\n", c_str);
}
free(s);
exit(EXIT_SUCCESS);
}
著者: 胡金庫