Weird realloc() error

A

alex323

Hey. I must have an array that can be resized dynamically. I have coded
an implementation of it using malloc/realloc, but I am getting a
runtime error as seen below in GDB:

*** glibc detected *** realloc(): invalid next size: 0x08054828 ***

Program received signal SIGABRT, Aborted.
[Switching to Thread -1218516048 (LWP 14211)]
0xffffe410 in __kernel_vsyscall ()
(gdb) bt
#0 0xffffe410 in __kernel_vsyscall ()
#1 0xb7e2f9b1 in raise () from /lib/tls/i686/cmov/libc.so.6
#2 0xb7e312c9 in abort () from /lib/tls/i686/cmov/libc.so.6
#3 0xb7e636ea in __fsetlocking () from /lib/tls/i686/cmov/libc.so.6
#4 0xb7e6bba2 in free () from /lib/tls/i686/cmov/libc.so.6
#5 0xb7e6ca66 in realloc () from /lib/tls/i686/cmov/libc.so.6
#6 0x0804901f in sockstate_handle_outgoing (arg=0x804c008) at
sockstate.c:75
#7 0xb7f3a361 in start_thread () from
/lib/tls/i686/cmov/libpthread.so.0
#8 0xb7ecfbde in clone () from /lib/tls/i686/cmov/libc.so.6
(gdb)

The code is as follows:

ufds = malloc(sizeof(struct pollfd)*numconns); /* Where ufds is a
pointer to a pollfd, and numconns is the number of sockets that will be
stored in ufds. */

[...]

if( the number of sockets has changed ) {
ufds = realloc(ufds, sizeof(struct pollfd)*numconns); /* numconns
is set to the new number, which could be higher or lower. This is the
line GDB is reporting (sockstate.c:75) */
}

Anyone have any ideas on how to resolve this problem?

Thanks,
Alex
 
B

Ben Pfaff

Hey. I must have an array that can be resized dynamically. I have coded
an implementation of it using malloc/realloc, but I am getting a
runtime error as seen below in GDB:
[...]

if( the number of sockets has changed ) {
ufds = realloc(ufds, sizeof(struct pollfd)*numconns); /* numconns
is set to the new number, which could be higher or lower. This is the
line GDB is reporting (sockstate.c:75) */
}

Anyone have any ideas on how to resolve this problem?

The line being reported as in error is probably not the real
problem. The root problem is probably due to overwriting memory
elsewhere in your program.

My guess is that you are using GNU/Linux on x86. In that case, I
recommend running your program under valgrind. Chances are that
it will pinpoint the real problem.
 
J

Jack Klein

Hey. I must have an array that can be resized dynamically. I have coded
an implementation of it using malloc/realloc, but I am getting a
runtime error as seen below in GDB:

*** glibc detected *** realloc(): invalid next size: 0x08054828 ***

Program received signal SIGABRT, Aborted.
[Switching to Thread -1218516048 (LWP 14211)]
0xffffe410 in __kernel_vsyscall ()
(gdb) bt
#0 0xffffe410 in __kernel_vsyscall ()
#1 0xb7e2f9b1 in raise () from /lib/tls/i686/cmov/libc.so.6
#2 0xb7e312c9 in abort () from /lib/tls/i686/cmov/libc.so.6
#3 0xb7e636ea in __fsetlocking () from /lib/tls/i686/cmov/libc.so.6
#4 0xb7e6bba2 in free () from /lib/tls/i686/cmov/libc.so.6
#5 0xb7e6ca66 in realloc () from /lib/tls/i686/cmov/libc.so.6
#6 0x0804901f in sockstate_handle_outgoing (arg=0x804c008) at
sockstate.c:75
#7 0xb7f3a361 in start_thread () from
/lib/tls/i686/cmov/libpthread.so.0
#8 0xb7ecfbde in clone () from /lib/tls/i686/cmov/libc.so.6
(gdb)

The code is as follows:

ufds = malloc(sizeof(struct pollfd)*numconns); /* Where ufds is a
pointer to a pollfd, and numconns is the number of sockets that will be
stored in ufds. */

[...]

if( the number of sockets has changed ) {
ufds = realloc(ufds, sizeof(struct pollfd)*numconns); /* numconns
is set to the new number, which could be higher or lower. This is the
line GDB is reporting (sockstate.c:75) */
}

Anyone have any ideas on how to resolve this problem?

There is a 99% or better probability that you are writing past the end
of the allocated memory between the call to malloc() and the call to
realloc().

By the way, NEVER use the same pointer to receive the return of
realloc(). If the reallocation fails due to insufficient memory or
some other reason, it returns NULL and the original memory is still
allocated. But you have overwritten the original pointer with NULL,
and can no longer free it, thus creating an instant memory leak.

You should do this:

struct follfd *ufds, *temp;

ufds = malloc( /*... */ );

if (!udfs)
{
/* error handling */
}

/* ... */

temp = realloc(udfs, /* ... */);

if (!temp)
{
/* error handling */
free(udfs);
}
else
{
udfs = temp;
}
 
K

Keith Thompson

Jack Klein said:
By the way, NEVER use the same pointer to receive the return of
realloc(). If the reallocation fails due to insufficient memory or
some other reason, it returns NULL and the original memory is still
allocated. But you have overwritten the original pointer with NULL,
and can no longer free it, thus creating an instant memory leak.

*Unless* your response to an allocation failure will always be to
abort the program, perhaps after some cleanup code that doesn't need
to refer to the leaked object.
 
J

Jack Klein

*Unless* your response to an allocation failure will always be to
abort the program, perhaps after some cleanup code that doesn't need
to refer to the leaked object.

My clean up code often attempts to save the contents of the original
block to a file before exiting, in an attempt to allow for later
salvage of the data.

There are also quite a few cases where the original operation can be
carried out, albeit more slowly, in the existing amount of memory, or
by manually swapping out to a file.

In general, it's never a good idea to lose the original pointer on a
reallocation failure. It is far more benign to have it in the
instances where you might not need it, to need it and not have it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top