0

I am writing a code in C, and I have a problem allocating exactly the size I need. I use a while loop and realloc function , and when the loop is done I have a spare memory (+1 than what I need). and I cant find a way to allocate the exact size I need.

user3819295
  • 861
  • 6
  • 19
  • Don't allocate arrays 1 by 1 like that; it ends up being expensive. Keep a separate record of the number of allocated records and the number in use. When you allocate more memory, allocate twice as much each time. This avoids quadratic behaviour which linear allocation does not. – Jonathan Leffler Mar 29 '15 at 20:37
  • Or, alternatively, read into a local variable `Student data;` and allocate more data in the array when you know there's another student's worth of data to store. – Jonathan Leffler Mar 29 '15 at 20:38
  • Thanks for respond Jonathan. can you please show me what you mean by using the alternatively way that you mentioned? – user3819295 Mar 29 '15 at 20:47

1 Answers1

0

Incrementing the array size one record at a time — not good for performance, but relatively simple:

int InputData(Student **p_array, FILE*fp)
{
    Student *temp = 0;
    Student data;
    int i = 0;

    while (fscanf(fp, "%s%d%d%d", data.name, &data.grades[0],
                  &data.grades[1], &data.grades[2]) == 4)
    {
        size_t space = ++i * sizeof(Student);
        Student *more = (Student *)realloc(temp, ++i * sizeof(Student));
        if (more == NULL)
            Error_Msg("Memory allocation failed!");
        temp = more;
        temp[i-1] = data;
    }

    *p_array = temp;
    return i;
}

Note that you could (maybe should) free(temp) before calling Error_Msg(). Note that the realloc() does not use the ptr = realloc(ptr, new_size) idiom because that loses (leaks) the previously allocated memory if the reallocation fails.

One other option — shrink your allocation before returning:

int InputData(Student **p_array, FILE*fp)
{
    int i = 1;
    Student *temp = (Student *)malloc(sizeof(Student));

    if (temp == NULL)
        Error_Msg("Memory allocation failed!");
    while (fscanf(fp, "%s%d%d%d", temp[i - 1].name, &temp[i - 1].grades[0],
                  &temp[i - 1].grades[1], &temp[i - 1].grades[2]) == 4)
    {
        i++;
        temp = (Student*)realloc(temp, sizeof(Student)*i);
        if (temp == NULL)
            Error_Msg("Memory allocation failed!");
    }
    assert(i > 0);
    temp = (Student *)realloc(temp, sizeof(Student) * (i - 1));
    *p_array = temp;
    return i;
}

I don't like this because of the temp = realloc(temp, new_size) idiom, but you could fix that too.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278