PDA

View Full Version : [C]errori redefinition e previous declaration


braian
13-06-2008, 19:50
Salve a tutti, sto facendo un progetto in c in cui ho 3 file header: tipiAllocatore.h, allocatore.h, funzioniServizio.h e 1 file c allocatore.c

In uno header ho le strutture dati che utilizzo e che sembrano darmi problemi, specialmente con gli ide Eclipse o Netbeans.

in allocatore.h ho le definizioni delle funzioni,
in funzioniServizio le definizioni delle funzioni di servizio,
il file tipiAllocatore.h è il seguente:


/*
macro per valori logici
*/
#define TRUE 1
#define FALSE 0
/*
macro per la gestione degli errori
*/
#define ERROR_INIZIALE -1
#define ERROR_NESSUNERRORE 0
#define ERROR_MALLOC 1
#define ERROR_NUMEROHANDLE 2
#define ERROR_SPAZIOLIBERO 3
#define ERROR_ZEROVAL 4
#define ERROR_NULLVAL 5
#define ERROR_POSIZIONE 6

/*
struttura usata per rappresentare un byte
*/
typedef unsigned char byte;

/*
struttura usata per rappresentare un valore logico
*/
typedef int boolean;

/*
struttura dati usata per rappresentare gli elementi della tabellaAllocazioni
*/
typedef struct
{
int id;
int base;
int limite;
struct elementoTabella next;
}elementoTabella;



/*
struttura dati usata per rappresentare lo heap
*/
typedef struct
{
int spazioLibero;
byte* strutturaHeap;
int dimensioneHeap;
int numeroHandle;
int numeroAttualeHandle;
elementoTabella* tabellaAllocazioni ;
}heap;




e l' allocatore.c il seguente:


#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "tipiAllocatore.h"
#include "allocatore.h"
#include "funzioniServizio.h"

/*

typedef unsigned char byte;


struttura dati usata per rappresentare gli elementi della tabellaAllocazioni

typedef struct elementoTabella
{
int id;
int base;
int limite;
}

/*
struttura dati usata per rappresentare lo heap

typedef struct heap
{
byte* strutturaHeap;
int dimensioneHeap;
int numeroHandle;
int numeroAttualeHandle;
elementoTabella* tabellaAllocazioni
}

*/

static int codiceErrore=ERROR_INIZIALE;


/*
crea un nuovo heap, capace di gestire al più nhandles handle, e con uno spazio per i dati di size bytes.
*/
heap *createH(int nhandles, int size)
{
if (size == 0)
{
codiceErrore = ERROR_ZEROVAL;
return NULL;
}
if (nhandles == 0)
{
codiceErrore = ERROR_ZEROVAL;
return NULL;
}
heap* _heap = (heap*)malloc(sizeof(heap));
if (_heap == NULL)
{
codiceErrore = ERROR_MALLOC;
return NULL;
}
_heap->spazioLibero = size;
_heap->dimensioneHeap = size;
_heap->numeroHandle = nhandles;
_heap->numeroAttualeHandle = 0;
_heap->tabellaAllocazioni = NULL;
_heap->strutturaHeap = (byte*)malloc(size);
if (_heap->strutturaHeap == NULL)
{
codiceErrore = ERROR_MALLOC;
return NULL;
}
}

/*
alloca size bytes nello heap h, restituisce il puntatore a un handle (o NULL in caso di errore). Se c'è sufficiente spazio disponibile, ma non contiguo, effettua una ricompattazione e poi alloca il blocco.
*/
void **allocH(heap *h, int size)
{
if(h == NULL)
{
codiceErrore = ERROR_NULLVAL;
return NULL;
}
if(size == 0)
{
codiceErrore = ERROR_ZEROVAL;
return NULL;
}
if(h->numeroAttualeHandle == h->numeroHandle)
{
codiceErrore = ERROR_NUMEROHANDLE;
return NULL;
}
if(h->spazioLibero<size)
{
codiceErrore = ERROR_SPAZIOLIBERO;
return NULL;
}
elementoTabella* elemento = (elementoTabella*)malloc(sizeOf(elementoTabella));
if (elemento == NULL)
{
codiceErrore = ERROR_MALLOC;
return NULL;
}
elemento->next = NULL;
int posizione = calcolaPosizione(h,size);
if (posizione = -1)
{
codiceErrore = ERROR_POSIZIONE;
return NULL;
}
}

/*
libera la memoria allocata dall'handle handle nello heap h. L'handle deve essere stato ottenuto da una precedente chiamata a allocH().
*/
void freeH(heap *h, void **handle);

/*
restituisce la quantità di spazio libero nello heap h (ovvero, la somma della dimensione di tutti gli eventuali frammenti liberi).
*/
int availH(heap *h);

/*
forza una ricompattazione dello heap h.
*/
void compactH(heap *h);

/*
distrugge lo heap h; dopo questa operazione, tutti gli handle ottenuti da allocH() su quello heap sono invalidi.
*/
void destroyH(heap *h);




int _error()
{
return codiceErrore;
}




/****************************************************************
* *
* FUNZIONI DI SERVIZIO *
* *
****************************************************************/


/*
Calcola l'offset rispetto alla base dello heap _heap, in cui lo spazio da allocare; eventalmente compatta lo heap.
*/
static int calcolaPosizione(heap* _heap, int size)
{
if((_heap == NULL) || (size == 0))
{
return -1;
}
boolean disponibile = FALSE;
elementoTabella* riga = _heap->tabellaAllocazioni;
while ( riga != NULL )
{
//se c'è una riga un altra area di memoria allocata con indirizzo superiore
if(riga->next != NULL)
{
//se c'è abbastanza spazio tra le 2 aree di memoria considerate per inserire quella nuova, vi inserisco quest'ultima
if(riga->next->base-(riga->limite)>size)
{
return riga->limite+1;
}
}
//altrimenti se non ci sono altre aree di memoria ma lo spazio fino alla fine dello heap è sufficente a contenere la nuova area di memoria
else if((_heap->dimensioneHeap-riga->limite)>size)
{
return riga->limite+1;
}
riga=riga->next;
}
compactH(_heap);

}



gli errori che ho come detto sono sulle strutture e mi vengono dati con eclipse e netbeans ma non con la compliazione da riga di comando: praticamente per ogni typedef usato ho gli errori REDEFINITION OF TYPEDEF <TIPODATO>
e anche PREVIOUS DEFINITION OF <TIPODATO> WAS HERE
oltre ad un errore nella struct elementoTabella
typedef struct elementoTabella
{
int id;
int base;
int limite;
struct elementoTabella next;
};
dove anche con la compilazione da riga di comando ho l'errore FIELD NEXT HAS INCOMPLETE TYPE

Vi sarei davvero grato se poteste darmi una mano
:muro: :help:

braian
14-06-2008, 08:38
up, sarebbe davvero importante:help:

71104
14-06-2008, 08:47
proteggi dall'inclusione multipla: #pragma once all'inizio di ciascun header se il compilatore la supporta, altrimenti:

#ifndef __INVENTATI_UNA_MACRO__
#define __INVENTATI_UNA_MACRO__

// codice dell'header

.
.
.

#endif

braian
14-06-2008, 10:09
Si, è vero, grazie...ci ero arrivato grazie a Dio... casualmente ho inserito in eclipse un header che aveva all'inizio ifndef Macro.... e andava bene, ho risolto anche l'altro errore che era perchè chiamavo sizeOf invecie di sizeof.... se hai tempo e non ti dispiace potresti spiegarmi meglio il fatto di dover proteggere dalla inclusione doppia e di usare le macro in questo modo? Questo errore non mi sembrava lo desse se compilavo da riga di comando...ma forse mi sbaglio...

per l'altro errore sulla lista che intendevo fare ho risolto cambiando da :

typedef struct elementoTabella
{
int id;
int base;
int limite;
struct elementoTabella next;
};

a

typedef struct elementoTabella
{
int id;
int base;
int limite;
struct elementoTabella next;
}elementoTabella;



grazie ancora:D

71104
14-06-2008, 12:56
se hai tempo e non ti dispiace potresti spiegarmi meglio il fatto di dover proteggere dalla inclusione doppia e di usare le macro in questo modo? non so come tu compili da linea di comando, comunque: la direttiva di preprocessore #include equivale concettualmente ad incollare al posto di quella riga pari pari l'intero file sorgente indicato, ne' più ne' meno; C e C++ non hanno il concetto di import, di package, e cose simili, ma solo di inclusione. l'errore in cui ti sei imbattuto è dovuto ad una combinazione di inclusioni che durante la compilazione di uno dei sorgenti hanno provocato l'inclusione multipla di uno stesso header, per esempio perché quell'header è stato incluso sia dal sorgente compilato sia da un altro header a sua volta incluso nel sorgente compilato. il risultato è che il compilatore ha letto due volte l'header, incontrando due volte tutte le definizioni (vale non solo per le typedef ma per qualsiasi altra cosa: anche per i #define ad esempio).

con la protezione #ifndef/#define fai in modo che l'header venga letto dal compilatore una volta sola perché esso definisce una macro che fa saltare le letture successive a partire dalla seconda inclusa. per risparmiarti il lavoro di fantasia nel definire i nomi delle macro che proteggono gli headers e la relativa naming convention (che deve fare in modo che quei nomi non collidano accidentalmente con altre macro) i compilatori decenti offrono una direttiva pragma non standard, "#pragma once"; i compilatori Microsoft e Intel ce l'hanno, il MinGW ce l'ha, penso ce l'abbia anche il gcc di Linux.

braian
14-06-2008, 14:29
grazie mille sei stato chiarissimo :D