0

要素を入れているときにスペースがなくなったときに構造体の配列を再割り当てしようとしていますが、再割り当てstderrを受け取り続けています。構造体の配列には、最終的に 235,000 の要素が含まれます。初期開始サイズを 100,000 に設定すると、再割り当てしようとすると stderr を受け取ります。初期開始サイズを 300,000 に設定すると、realloc ステートメントに到達しないため、エラーは発生しません。

#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>

#define BUFFERLEN 200
#define START_SIZE 100000
#define GROW 1000
#define TRUE 1
#define FALSE 0

typedef struct{
    char *forw;
    char *back;
} word;

typedef struct{
    char *entry;
} single_words;


FILE *words;
/*-------------Function Prototypes------------*/
void reverse(char* string, char* revstr, int len);
int search_struct(char* find, word* words, int length);
int compare(const void* eventa, const void* eventb);
int length(char* string);


int main(void)
{
    char *buffer;
    int letter_index[26];
    char alpha[] = "abcdefghijklmnopqrstuvwxyz";
    int i=0, found = FALSE, strlen=0, letter=0;
    word *word_storage;
    single_words *output_storage;
    int num_words = 0, size = 0;
    int num_output = 0, output_size = 0;

    /*buffer for the input strings of the words in the input file*/
    buffer = (char*) malloc (sizeof(char)*BUFFERLEN);
        if(!buffer){
            fprintf(stderr, "Error in buffer string mem alloc\n");
            exit(1);
        }   

    /*Initializing the array of structs to store the forward and reverse of each word*/
    word_storage = (word*) malloc (sizeof(word)*START_SIZE);
        if(!word_storage){
            fprintf(stderr, "Error in word_storage string mem alloc\n");
            exit(1);
        }
        size = START_SIZE;

    /*Initializing the array of structs for the output*/
    output_storage = (single_words*) malloc (sizeof(single_words)*START_SIZE);
        if(!output_storage){
            fprintf(stderr, "Error in output_storage mem alloc\n");
            exit(1);
        }
        output_size = START_SIZE;   

    /*Set the letter index 0(which is a) to the first character*/
    letter_index[0] = 0;

    words = fopen("words", "r");

    /*Read the words(forward and reverse) in from stdin into the word_storage*/
    while(fgets(buffer, BUFFERLEN, words) != NULL){
        buffer = strtok(buffer, "\n");
        strlen = length(buffer);
        if (num_words < size){
            /*Allocate memory for the forward and reverse strings*/
            word_storage[num_words].forw = (char *) malloc (sizeof(char) * strlen);
                if(!word_storage[num_words].forw){
                    free(word_storage[num_words].forw);
                    fprintf(stderr, "word_storage forward string malloc was unsuccessful");
                    exit(1);
                }
            word_storage[num_words].back = (char *) malloc (sizeof(char) * strlen);
                if(!word_storage[num_words].back){
                    free(word_storage[num_words].back);
                    fprintf(stderr, "word_storage forward string malloc was unsuccessful");
                    exit(1);;
                }               

            /*Store the forward and reverse in the strings*/
            strncpy(word_storage[num_words].forw, buffer, strlen);
            reverse(word_storage[num_words].forw, word_storage[num_words].back, strlen);
            printf("%d: %s %s\n", num_words, word_storage[num_words].forw, word_storage[num_words].back);

            /*Increment the letter if it changes*/
            if(word_storage[num_words].forw[0] != alpha[letter]){
                letter++;
                letter_index[letter] = num_words + 1;
            }
            num_words++;
        }
        else{
            /*Increase the size of word_storage*/
            word_storage = (word*) realloc (word_storage, sizeof(word) * size * GROW);
                if(!word_storage){
                    free(word_storage);
                    fprintf(stderr, "Error in word_storage realloc string mem realloc\n");
                    exit(1);
                }
            size = size * GROW;
        }       
    }


    return 0;
}

再割り当てエラーは次の場所で発生します。

word_storage = (word*) realloc (word_storage, sizeof(word) * size * GROW);
    if(!word_storage){
      free(word_storage);
      fprintf(stderr, "Error in word_storage realloc string mem realloc\n");
      exit(1);
     }
     size = size * GROW;
4

2 に答える 2

1

したがって、最初は 100,000 に設定sizeします。START_SIZEそれを使い切ると、sizeof(word) * size * GROWバイトを割り当てようとします。sizeof(word)おそらく16バイトです。sizeこれは 100000 であり、 1000 であることがわかっていGROWます。これで 100,000,000 エントリに十分なスペースが得られ、そのうち 235,000 を使用することになります。割り当ては少し寛大な側にあるようです。

100,000,000 エントリの合計スペースは 1,600,000,000 バイトです。多くのように思えますが、最近では多くのデスクトップ マシンがそれを処理できます。しかし、それが失敗してもそれほど驚くことではないようです。realloc

おそらくGROW、2 のようにもっと合理的なものを作成する必要があります。

ところで、word_storage が NULL であることを確認したら、 を呼び出しても意味がありませんfree(word_storage)。ノーオペレーションなので害はfree(NULL)ありませんが、同じ理由で何の役にも立ちません。

于 2013-10-06T06:34:17.970 に答える
0

サイズに 1000 を掛けすぎています (非常に指数関数的な成長 1 -> 1000 -> 1000 000 -> 1000 000 000 ...) errno。代わりに提案します

 size_t newsize = 3*size/2 + 1000;
 word_storage = realloc(word_storage, sizeof(word)*newsize);
 if (!word_storage) {
     fprintf(stderr, "Cannot grow storage to %ld size, %s\n",
                     (long) newsize, strerror(errno));
     exit (EXIT_FAILURE);
 }
 else size = newsize;

次に、初期サイズ 1000 から開始すると、1000 -> 2500 -> 4750 -> 8125 -> 13187 -> 20780 というより合理的な進行が得られます。さらに重要なのは、無駄なメモリの最大 50% を消費していることです。 、ほぼ 1000 倍ではありません。

于 2013-10-06T06:33:57.423 に答える