頻繁なメモリ割り当てを必要とするプログラムで作業しているときに、説明できない動作に遭遇しました。回避策を実装しましたが、以前の実装が機能しなかった理由に興味があります。状況は次のとおりです。
ポインタのメモリ再割り当てが機能する
これはベスト プラクティスではないかもしれません (そうであれば教えてください) が、渡されたポインターが NULL の場合、realloc は新しいメモリを割り当てることができることを思い出します。以下は、ファイル データを一時バッファーに読み込み、*data と memcopy コンテンツに適切なサイズを割り当てる例です。
私はそのようなファイル構造を持っています
typedef struct _my_file {
int size;
char *data;
}
そして、メモリの再割り当てとコピーのコードは次のようになります。
// cycle through decompressed file until end is reached
while ((read_size = gzread(fh, buf, sizeof(buf))) != 0 && read_size != -1) {
// allocate/reallocate memory to fit newly read buffer
if ((tmp_data = realloc(file->data, sizeof(char *)*(file->size+read_size))) == (char *)NULL) {
printf("Memory reallocation error for requested size %d.\n", file->size+read_size);
// if memory was previous allocated but realloc failed this time, free memory!
if (file->size > 0)
free(file->data);
return FH_REALLOC_ERROR;
}
// update pointer to potentially new address (man realloc)
file->data = tmp_data;
// copy data from temporary buffer
memcpy(file->data + file->size, buf, read_size);
// update total read file size
file->size += read_size;
}
ポインタへのポインタのメモリ再割り当てが失敗する
しかし、ここで私は混乱しています。NULL ポインタを再割り当てすると新しいメモリが割り当てられるという同じ考えを使用して、引数の文字列を解析し、引数ごとにポインタをポインタに割り当て、そのポインタが指すポインタをポインタに割り当てます。コードの方が説明しやすいかもしれません:
これは構造です:
typedef struct _arguments {
unsigned short int options; // options bitmap
char **regexes; // array of regexes
unsigned int nregexes; // number of regexes
char *logmatch; // log file match pattern
unsigned int limit; // log match limit
char *argv0; // executable name
} arguments;
そして、メモリ割り当てコード:
int i = 0;
int len;
char **tmp;
while (strcmp(argv[i+regindex], "-logs") != 0) {
len = strlen(argv[i+regindex]);
if((tmp = realloc(args->regexes, sizeof(char **)*(i+1))) == (char **)NULL) {
printf("Cannot allocate memory for regex patterns array.\n");
return -1;
}
args->regexes = tmp;
tmp = NULL;
if((args->regexes[i] = (char *)malloc(sizeof(char *)*(len+1))) == (char *)NULL) {
printf("Cannot allocate memory for regex pattern.\n");
return -1;
}
strcpy(args->regexes[i], argv[i+regindex]);
i++;
}
これをコンパイルして実行すると、実行時エラー「realloc: 無効なポインター」が発生します。
明らかな何かが欠けているに違いありませんが、デバッグを試みて解決策をオンラインで5時間検索しようとしてもあまり達成できなかった後、2つのループを実行しました.1つは引数の数を数え、それに十分なスペースをmallocし、2番目のループは引数とそれを strcpys します。
この動作の説明は大歓迎です! その理由を知りたいです。