0

My professor gave us an "assignment" to find why realloc() won't work in this specific example. I tried searching this site and I think that it won't work because there is no real way to determine the size of a memory block allocated with malloc() so realloc() doesn't know the new size of the memory block that it needs to reallocate.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
int main ()
{
    MEMORYSTATUS memInfo;
    memInfo.dwLength = sizeof(MEMORYSTATUS);
    GlobalMemoryStatus(&memInfo);
    double slobodno = memInfo.dwAvailVirtual/1024./1024.;

    printf("%g MB\n",slobodno);
    int br=0,i,j;

    char **imena,*ime,*temp,*bbb=NULL;
    imena=(char**) malloc(sizeof(char*)*(br+1));
    while(1)
    {
        printf("Unesite ime: ");
        ime=(char*) malloc(sizeof(char)*4000000);
        gets(ime);
        printf("%u\n", strlen(ime));
        ime=(char*) realloc(ime,strlen(ime)+1);

        GlobalMemoryStatus(&memInfo);
        slobodno = memInfo.dwAvailVirtual/1024./1024.;
        printf("%g MB\n",slobodno);

        if (strcmp(ime,".")==0)
           {free(ime);free(imena[br]);break;}
        imena[br++]=ime;
        imena=(char**) realloc(imena,sizeof(char*)*(br+1));
    }

    for (i=0;i<br-1;i++)
        for (j=i+1;j<br;j++)
            if (strcmp(imena[i],imena[j])>0)
            {
                temp=imena[i];
                imena[i]=imena[j];
                imena[j]=temp;
            }


    //ovde ide sortiranje
    for (i=0;i<br;i++)
        printf("%s\n",imena[i]);

    for(i=0;i<br;i++)
       free(imena[i]);

    free(imena);

    return 0;
}

Note: Professor added the lines for printing out the available memory so we can see that realloc() doesn't work. Every new string we enter just takes up sizeof(char)+4000000 bytes and can't be reallocated. I'm trying to find out why. Thanks in advance

Mike
  • 47,263
  • 29
  • 113
  • 177
  • 1
    And *pretty please,* don't cast the *friggin'* return value of the *poor damn* `malloc()`! It's so ugly my compiler vomits assembly... –  Nov 07 '12 at 20:17
  • The code seems to work without any erros. I enter `123qwe.` and get `123qwe`. – alk Nov 07 '12 at 20:33
  • Forgot to mention that memory consumption is moderate and that I testet on Linux. – alk Nov 07 '12 at 20:41
  • Thank you for taking the time to comment. When I tried entering "." as the first input it just prints out the length of the string I entered (in this case 1) and stops the program. – user1807181 Nov 07 '12 at 20:50

4 Answers4

3

I have a feeling that it has something to do with the page sizes on Windows. For example, if you change 4000000 to 400000, you can see that the memory can be re-used.

I think that allocating 4000000 forces Windows to use "huge" page sizes (of 4MB) and for some (unknown to me) reason, realloc doesn't work on them in the way that you would expect (i.e. making unused memory available for other allocations).

This seems to be related to Realloc() does not correctly free memory in Windows, which mentions VirutalAlloc, but I'm not sure it clarifies the exact reason that realloc doesn't work.

Community
  • 1
  • 1
Omri Barel
  • 9,182
  • 3
  • 29
  • 22
  • Once again I can't "vote up" since I'm new but I sure would. This answers my question completely and you even provided a link to a similar problem which I appreciate greatly. I'll try looking for more info now that I have a starting point. Thank you so much! – user1807181 Nov 07 '12 at 20:40
  • @alk basically the C standard library is broken on Windows. –  Nov 08 '12 at 06:05
0

From MSDN:

The memblock argument points to the beginning of the memory block. If memblock is NULL, realloc behaves the same way as malloc and allocates a new block of size bytes.

So the line ime=(char*) realloc(NULL,sizeof(char)*4000000); just malloc's new memory each time.

prprcupofcoffee
  • 2,950
  • 16
  • 20
  • Yes, that was me trying to see if that would help. Originally it was malloc(sizeof(char)*4000000);, i think it's the same thing, the problem is with the next realloc, since that won't work. – user1807181 Nov 07 '12 at 20:23
0

The problem is not that realloc doesn't know the size of the original block. Even though that information is not available for us programmers, it is required to be available to realloc (even if the block was allocated with malloc or calloc).

The line

ime=(char*) realloc(ime,strlen(ime)+1);

looks like it is shrinking the previously allocated block to fit the contents exactly, but there is no requirement that is actually shrinks the block of memory and makes the remainder available again for a new allocation.

Edit

Another thing I just thought of: The shrinking with realloc might work OK, but the memory is not returned by the runtime library to the OS because the library keeps it around for a next allocation. Only, the next allocation is for such a large block that it does not fit the memory freed up with realloc.

Bart van Ingen Schenau
  • 15,488
  • 4
  • 32
  • 41
  • I wanted to "vote up" this but i couldn't since i just joined. Your answer is close i think, the thing is, the professor said "let's allocate too much memory for a string and then cut off the memory that wasn't used with realloc. Isn't that how it works? – user1807181 Nov 07 '12 at 20:26
  • @user1807181: That is how realloc conceptually works. In practice, shrinking memory blocks with realloc might not do anything. – Bart van Ingen Schenau Nov 07 '12 at 20:35
0

realloc doesn't free memory. These functions work with a big block of memory (called a "heap") and carve chunks out when you call realloc/malloc/calloc. If you need more memory than is in the heap at the moment, then the heap is expanded by asking the operating system for more memory.

When you call realloc to make a memory block smaller, all that happens is that the memory you don't need any more is made available for *alloc to hand out again on a different request. Neither realloc nor free ever shrink the heap to return memory back to the operating system. (If you need that to happen, you need to call the operating system's native memory allocation procedures, such as VirtualAlloc on Windows.)

prprcupofcoffee
  • 2,950
  • 16
  • 20
  • Thank you for the answer, I think I understood you. realloc doesn't really free memory it just makes it available for more allocations? – user1807181 Nov 07 '12 at 20:46
  • @alk - no, it's not a Windows speciality. Newer UNIX/Linux implementations may return memory to the operating system (I don't know; don't have one to play around with), but in older implementations the behavior was the same - the *alloc library managed its own heap, calling break(2) to get more OS memory, and it was either not possible or not performant to use break() to free/allocate memory like that. – prprcupofcoffee Nov 07 '12 at 21:01