2012-09-01 6 views
13

ich die folgende Fehlermeldung beim Ausführen ac Programm (i!):Doppel frei oder Korruption Fehler in c-Programm

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

Ich glaube, dies zu freiem gebührt() am Ende des Programms aufgerufen wird, aber ich kann nicht herausfinden, wo die Malloc'd Erinnerung vorher befreit wird. Hier ist der 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; 
} 

Dies wird erstellt mit:

gcc -Wall -g -lm test.c 

Valgrind:

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

gibt:

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

Ich habe nicht viel Erfahrung mit Sprachen, die ihre eigenen mich nicht verwalten mory automatisch (daher diese Übung in c, um ein bisschen zu lernen), aber stecke fest. Jede Hilfe wäre willkommen.

Der Code soll Teil eines additiven Audio-Synthesizers sein. In dieser Hinsicht funktioniert es und gibt die richtige Ausgabe in ptr gespeichert.

Danke.

Antwort

19
double *ptr = malloc(sizeof(double *) * TIME); 
/* ... */ 
for(tcount = 0; tcount <= TIME; tcount++) 
         ^^ 
  • Sie überschreiten das Array. Entweder <=-< oder alloc ändern SIZE + 1 Elemente
  • Ihre malloc ist falsch, Sie wollen sizeof(double) statt sizeof(double *)
  • Als ouah Kommentare, die aber nicht direkt auf Ihrem Korruption Problem verknüpft, verwenden Sie *(ptr+tcount) ohne Initialisierung es

  • nur als Stil nicht te, könnte man ptr[tcount] statt *(ptr + tcount)
  • verwenden möchten Sie brauchen nicht wirklich zu malloc + free da Sie bereits SIZE
+0

Auch '* (ptr + tcount) + = Sinus;' aber das Array wird nie initialisiert. – ouah

+0

@ouah Guter Anruf. Dieses Programm hat mehr Löcher als ein Schweizer Käse. – cnicutar

+0

Schweizer Käse in der Tat! Danke für Ihre Hilfe. Es sieht so aus, als ob ich noch einen Weg hätte, um Pointer und Malloc zu knacken. – user1640921

6

Ändern Sie diese Zeile

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

zu

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

Ich habe nicht den ganzen Code überprüft, aber meine Vermutung ist, dass der Fehler in ist der Malloc-Anruf.Sie haben

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

für

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

ersetzen, da Sie Größe für ein Doppel (nicht die Größe eines Zeigers auf einem Doppel) zuordnen wollen.

4

1 - Ihr malloc() ist falsch.
2 - Sie sind die Grenzen des zugewiesenen Speicher zu überschreiten
3 - Sie sollten initialisieren ist Ihr zugewiesenen Speicher

Hier wird das Programm mit allen notwendigen Veränderungen. Ich kompilierte und lief ... keine Fehler oder Warnungen.

#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

Über das 'memset': Alle Bits 0 bedeuten nicht unbedingt, dass der gespeicherte doppelte Wert 0 ist. – cnicutar

+0

@cnicutar Ist das, weil variable Variablendarstellungen implementiert sind? – Chimera

+0

Es ist, weil es keine Garantie gibt, dass alle Fließkommaformate 0 als alle Bits 0 dargestellt haben. – cnicutar