2012-09-01 25 views
13

ottengo l'errore seguente quando si esegue il programma ac (prec!):doppio libero o la corruzione di errore nel programma c

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

Credo che questo sia dovuto a free() essere chiamato alla fine del programma, ma non riesco a capire dove la memoria malloc'd sia stata liberata prima di questo. Ecco il codice:

#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; 
} 

Questa è compilato con:

gcc -Wall -g -lm test.c 

Valgrind:

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

dà:

==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) 

non ho molta esperienza con lingue che non gestiscono da sole me stesso mory automaticamente (quindi questo esercizio in c per imparare un po ') ma sono bloccato. Qualsiasi aiuto sarebbe apprezzato.

Il codice dovrebbe far parte di un sintetizzatore audio aggiuntivo. A tale riguardo funziona e fornisce l'output corretto memorizzato in ptr.

Grazie.

risposta

19
double *ptr = malloc(sizeof(double *) * TIME); 
/* ... */ 
for(tcount = 0; tcount <= TIME; tcount++) 
         ^^ 
  • sei oltrepassare la matrice. O cambiare <=-< o alloc SIZE + 1 elementi
  • tuo malloc è sbagliato, ti consigliamo invece di sizeof(double) sizeof(double *)
  • Come ouah commenti, anche se non direttamente collegato al tuo problema della corruzione, che si sta utilizzando *(ptr+tcount) senza inizializzare si

  • Proprio come un nessuno stile TE, si potrebbe desiderare di utilizzare ptr[tcount] invece di *(ptr + tcount)
  • Non avete davvero bisogno di malloc + free poiché si conosce già SIZE
+0

Anche '* (ptr + tcount) + = seno;' ma l'array non viene mai inizializzato. – ouah

+0

@ouah Buona chiamata. Questo programma ha più buchi di un formaggio svizzero. – cnicutar

+0

Formaggio svizzero davvero! Grazie per l'aiuto. Sembra che io abbia ancora un modo per andare davvero a decifrare i puntatori e malloc. – user1640921

6

Modificare questa linea

double *ptr = malloc(sizeof(double *) * TIME); 

a

double *ptr = malloc(sizeof(double) * TIME); 
3

Non ho controllato tutto il codice ma la mia ipotesi è che l'errore sia la chiamata Malloc.È necessario sostituire

double *ptr = malloc(sizeof(double*) * TIME); 

per

double *ptr = malloc(sizeof(double) * TIME); 

dal momento che si desidera assegnare dimensioni per un doppio (non la dimensione di un puntatore ad un doppio).

4

1 - Il tuo malloc() è errato.
2 - Si sono eccedere i limiti della memoria allocata
3 - Si dovrebbe inizializzare la memoria allocata

Ecco il programma con tutti i cambiamenti necessari. Ho compilato e gestito ... senza errori o avvisi.

#include <stdio.h> 
#include <stdlib.h> //malloc 
#include <math.h> //sine 
#include <string.h> 

#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); 
    //memset(ptr, 0x00, sizeof(double) * TIME); may not always set double to 0 
    for(tcount = 0; tcount < TIME; tcount++) 
    { 
     ptr[tcount] = 0; 
    } 

    tcount = 0; 
    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; 
} 
+1

Informazioni su 'memset': tutti i bit 0 non significano necessariamente che il doppio valore memorizzato è 0. – cnicutar

+0

@cnicutar È perché le rappresentazioni di variabili in virgola mobile sono definite dall'implementazione? – Chimera

+0

È perché non c'è alcuna garanzia che tutti i formati in virgola mobile abbiano 0 rappresentato come tutti i bit 0. – cnicutar