Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

double free or corruption (!prev) error in c program

Tags:

c

free

I get the following error when running a c program:

*** glibc detected *** ./a.out: double free or corruption (!prev): 0x080b8008 *** 

I believe this is due to free() being called at the end of the program, but I can't figure out where the malloc'd memory is being freed prior to this. Here is the code:

#include <stdio.h> #include <stdlib.h> //malloc #include <math.h>  //sine  #define TIME 255 #define HARM 32  int main (void) {     double sineRads;     double sine;     int tcount = 0;     int hcount = 0;     /* allocate some heap memory for the large array of waveform data */     double *ptr = malloc(sizeof(double *) * TIME);     if (NULL == ptr) {         printf("ERROR: couldn't allocate waveform memory!\n");     } else {         /*evaluate and add harmonic amplitudes for each time step */         for(tcount = 0; tcount <= TIME; tcount++){             for(hcount = 0; hcount <= HARM; hcount++){                 sineRads = ((double)tcount / (double)TIME) * (2*M_PI); //angular frequency                 sineRads *= (hcount + 1); //scale frequency by harmonic number                 sine = sin(sineRads);                  *(ptr+tcount) += sine; //add to other results for this time step             }         }         free(ptr);         ptr = NULL;          }     return 0; } 

This is compiled with:

gcc -Wall -g -lm test.c 

Valgrind:

valgrind --leak-check=yes ./a.out 

gives:

    ==3028== Memcheck, a memory error detector ==3028== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. ==3028== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info ==3028== Command: ./a.out ==3028==  ==3028== Invalid read of size 8 ==3028==    at 0x8048580: main (test.c:25) ==3028==  Address 0x41ca420 is 1,016 bytes inside a block of size 1,020 alloc'd ==3028==    at 0x4024F20: malloc (vg_replace_malloc.c:236) ==3028==    by 0x80484F8: main (test.c:15) ==3028==  ==3028== Invalid write of size 8 ==3028==    at 0x8048586: main (test.c:25) ==3028==  Address 0x41ca420 is 1,016 bytes inside a block of size 1,020 alloc'd ==3028==    at 0x4024F20: malloc (vg_replace_malloc.c:236) ==3028==    by 0x80484F8: main (test.c:15) ==3028==  ==3028==  ==3028== HEAP SUMMARY: ==3028==     in use at exit: 0 bytes in 0 blocks ==3028==   total heap usage: 1 allocs, 1 frees, 1,020 bytes allocated ==3028==  ==3028== All heap blocks were freed -- no leaks are possible ==3028==  ==3028== For counts of detected and suppressed errors, rerun with: -v ==3028== ERROR SUMMARY: 8514 errors from 2 contexts (suppressed: 14 from 7) 

I don't have much experience with languages which don't manage their own memory automatically (hence this exercise in c to learn a bit) but am stuck. Any help would be appreciated.

The code is supposed to be part of an additive audio synthesiser. In that respect it does work and gives the correct output stored in ptr.

Thanks.

like image 716
user1640921 Avatar asked Sep 01 '12 19:09

user1640921


People also ask

What is double free or corruption (! Prev ):?

Description. Double free errors occur when free() is called more than once with the same memory address as an argument. Calling free() twice on the same value can lead to memory leak.

What happens when double free in C?

A double free in C, technically speaking, leads to undefined behavior. This means that the program can behave completely arbitrarily and all bets are off about what happens.

Which tools can be used to Analyse double free problem in C programming?

You can use gdb, but I would first try Valgrind. See the quick start guide. Briefly, Valgrind instruments your program so it can detect several kinds of errors in using dynamically allocated memory, such as double frees and writes past the end of allocated blocks of memory (which can corrupt the heap).

How can double free be avoided?

Double Free A simple technique to avoid this type of vulnerability is to always assign NULL to a pointer after it has been freed. Subsequent attempts to free a null pointer will be ignored by most heap managers.


1 Answers

double *ptr = malloc(sizeof(double *) * TIME); /* ... */ for(tcount = 0; tcount <= TIME; tcount++)                          ^^ 
  • You're overstepping the array. Either change <= to < or alloc SIZE + 1 elements
  • Your malloc is wrong, you'll want sizeof(double) instead of sizeof(double *)
  • As ouah comments, although not directly linked to your corruption problem, you're using *(ptr+tcount) without initializing it

  • Just as a style note, you might want to use ptr[tcount] instead of *(ptr + tcount)
  • You don't really need to malloc + free since you already know SIZE
like image 119
cnicutar Avatar answered Oct 10 '22 01:10

cnicutar