error allocating memory with realloc(). how can i increase max_allowed in the system?

Giorgos Keramidas keramida at ceid.upatras.gr
Tue Aug 12 16:09:18 UTC 2008


On Tue, 12 Aug 2008 17:02:43 +0200, Jordi Moles Blanco <jordi at cdmon.com> wrote:
> Hi,
>
> i'm running a FreeBSD 7.0 amd64 machine and struggling with some C
> code i'm writing.
>
> I've had some trouble with this home-made script as it keeps crashing
> while launching a "realloc()" call.
>
> I narrowed down the problem and here i'm sending you a short example of
> code that crashes:
>
> *************
> #include <stdio.h>
> #include <stdlib.h>
>
> int main()
> {
>
>        int midataula;
>
>        midataula = 3000;
>
>        char *missatge = (char *)malloc(midataula * sizeof(char));
>
>        missatge[0]='h';
>        missatge[1]='o';
>        missatge[2]='l';
>        missatge[3]='a';
>
>        printf("\n\ntaula1: %s",missatge);
>
>        int voltes;
>        voltes = 0;
>
>        while(voltes<4)
>        {
>                midataula = midataula+500;
>                realloc(missatge, midataula * sizeof(char));
>                voltes++;
>        }

There's your problem.  realloc() works fine, but it *returns* the new
pointer; it does _not_ modify missatge "in place".

The program should work fine if you use size_t for midataula (it is the
'size' of an array, which may not necessarily fit in an 'int'), and if
you use realloc() correctly, as in:

        #include <stdlib.h>
        #include <err.h>

        size_t midataula;
        char *missatge;

        /*
         * DON'T cast the result of malloc().  It may 'hide' the bug of
         * a missing <stdlib.h> include, and cause troubles when
         * malloc() is implicitly defined by the compiler as:
         *
         *        int malloc(...);
         *
         * On a 64-bit machine converting a 64-bit pointer to `int' will
         * lose the high-order 32 bits of the address, and you will try
         * to access unexpected memory areas.
         */
        midataula = 3000;
        missatge = malloc(midataula * sizeof(*missatge));
        if (missatge == NULL)
                err(1, "malloc");

Then when you use realloc() keep both midataula and missatge in
temporary copies until you are sure that realloc() worked:

        while (voltes < 4) {
                char *tmp;
                size_t newsize;

                newsize = midataula + 500;
                tmp = realloc(missatge, newsize * sizeof(*missatge));
                if (tmp == NULL)
                        err(1, "realloc");

                /*
                 * Now that you know the resize has succeeded, update
                 * midataula and missatge.  realloc() is allowed to
                 * relocate missatge.  See the following note in its
                 * manpage:
                 *
                 *   Note that realloc() and reallocf() may move the
                 *   memory allocation, resulting in a different return
                 *   value than ptr.
                 */
                midataula = newsize;
                missatge = tmp;
        }

Right now you are calling realloc() as:

                realloc(missatge, newsize * sizeof(*missatge));

and throwing away the resulting pointer.  The first time that realloc()
discovers that the `resized' vector cannot fit in its original location,
it relocates the array, and returns the new location.  You throw away
that location and your next iteration through the loop tries to access
an invalid (already freed) memory region.

That's what causes your segmentation fault.



More information about the freebsd-questions mailing list