First Defined Here und multiple definition of new_measure/delete_measure



  • Hallo Leute,

    First Defined Here und multiple definition of new_measure/delete_measure

    ... sind die Fehlermeldungen meines Compilers. Aber ich habe die Funktion nicht das erste mal dort definiert, sondern bereits in der Measure.h ...

    #ifndef MEASURE_H_
    #define MEASURE_H_
    
    #define Measure struct measure
    
    #define maxNameLength 			20
    #define maxDescriptionLength  100
    #define maxHtmlLength 		  1000
    
    Measure {
    	// For identification
    	unsigned int id;
    
    	// For configuration and usability
    	char name[maxNameLength];
    	char description[maxDescriptionLength];
    	char html[maxHtmlLength];
    
    	// For optimization
    	short int active;
    	short valid;
    	short fixed;
    
    };
    
    Measure * new_measure (int i, char n[maxNameLength] , char d[maxDescriptionLength],char h[maxHtmlLength]);
    
    void delete_measure (Measure* m);
    
    #endif /*MEASURE_H_*/
    

    ... und so sieht die Measure.c Datei aus.

    #include "Measure.h"
    
    Measure * new_measure (int i, char n[maxNameLength] , char d[maxDescriptionLength],char h[maxHtmlLength]){ 
    
    	Measure* m;
    
    	m=(Measure*) malloc(sizeof(Measure));
    
    	m->id=i;
    	strcpy (m->name,n);
    	strcpy (m->description,d);
    	strcpy (m->html,h);
    	m->active=1;
    	m->valid=1;
    	m->fixed=0;
    
    	return m;		
      };
    
    void delete_measure (Measure* m) 
    
    	{
    		free (m);
    	};
    

    Was hab ich falsch gemacht? In einer anderen "Klasse" (ich weiß, es gibt in C keine Klassen) hat es auf genau diese Weise funktioniert.

    Vielen Dank,

    Peilnix



  • Measure {
    // For identification
    unsigned int id;

    // For configuration and usability
    char name[maxNameLength];
    char description[maxDescriptionLength];
    char html[maxHtmlLength];

    // For optimization
    short int active;
    short valid;
    short fixed;

    };

    da fehlt was. es sollte besser so aussehen:

    typedef struct Measure_t 
    {
    ...
    } Measure;
    

    🙂



  • ... erst mal danke für die Antwort. Ich habe es ausprobiert und die

    #define Measure struct measure gelöscht ... mit dem Ergebnis, dass anschließend die "Cell.h" Measure nicht mehr kannte. Also habe ich dort das gleiche gemacht. (#define löschen, typedef struct cell {...} Cell;)

    und zack, war das erste problem wieder da. kann es was mit forwarddeclaration zu tun haben

    Peilnix 😕



  • peilnix schrieb:

    und zack, war das erste problem wieder da. kann es was mit forwarddeclaration zu tun haben

    kann sein, mach in alle .h's sogennante 'include guards' rein
    --> http://en.wikipedia.org/wiki/Include_guard
    dann kannst du's kreuz und quer #includen.
    wichtig auch: niemals die structs und typedefs nochmals (doppelt) irgendwo anlegen.
    --> http://en.wikipedia.org/wiki/One_Definition_Rule
    🙂



  • includeguards überall, keine doppelte typedef ...

    und dann: plötzlich sah ich in der main.c ein include Measure.c in der ich keinen includeguard eingebaut hatte ... !!!

    ich wäre niemals drauf gekommen (auch wenn ich die guards und odr (wenn auch nicht unter diesen namen) kannte.

    deshalb vielen DANK, lieber undertaker!

    yippieh (kopfrot abschwell, durchatmen ... seufz, freudentanz),

    der peilnix



  • peilnix schrieb:

    und dann: plötzlich sah ich in der main.c ein include Measure.c in der ich keinen includeguard eingebaut hatte ... !!!

    Ich hoffe du hast das durch ein Include des Headers ersetzt, nicht die Implementation mit Include-Guards bestückt!?



  • ... ich habe tatsächlich nur c_vitro.h included.

    Naja, jetzt habe ich den abstrakten Datentyp Measure fertiggestellt und mit einer Funktion

    print_measure

    versehen ...

    #Measure.h
    
    #ifndef MEASURE_H_
    #define MEASURE_H_
    
    #include "c_vitro.h"
    
    Measure { 
    	// For identification
    	unsigned int id;
    
    	// For configuration and usability
    	char name[maxNameLength];
    	char description[maxDescriptionLength];
    	char html[maxHtmlLength];
    
    	// For optimization
    	short active;
    	short valid;
    	short fixed;
    
    };
    
    Measure * new_measure (int i, char n[maxNameLength] , char d[maxDescriptionLength],char h[maxHtmlLength]);
    
    void delete_measure (Measure* m);
    
    void print_measure (Measure* m);
    
    char* string_measure (Measure* m);
    
    #endif /*MEASURE_H_*/
    
    /////////////////////////////////////////////////////////////
    
    #Measure.c
    
    #include "Measure.h"
    
    Measure* new_measure (int i, char n[maxNameLength] , char d[maxDescriptionLength],char h[maxHtmlLength]){ 
    
    	Measure* m;
    
    	m=(Measure*) malloc(sizeof(Measure));
    
    	m->id=i;
    	strcpy (m->name,n);
    	strcpy (m->description,d);
    	strcpy (m->html,h);
    	m->active=1;
    	m->valid=1;
    	m->fixed=0;
    
    	return m;		
    }
    
    void delete_measure (Measure* m) {
    
    		free (m);
    
    }
    
    void print_measure (Measure* m) {
    
    	char* result=string_measure (m);
    	puts (result);
    
    }
    
    char* string_measure (Measure* m) {
    
    	char* result="";
    	char* temp="";
    	sprintf (temp, "Measure %s.\nId of measure is %d.\n",m->name,m->id);
    	strcat (result, temp);
    	sprintf (temp, "Description: %s.\nHTML-Doc: %s.\n",m->description,m->html);
    	strcat (result, temp);
    	if (m->active) strcat (result, "State:Active, ");
    	else strcat (result, "State:\nNot Active, ");
    	if (m->valid) strcat (result, "valid, ");
    	else strcat (result, "not valid, ");
    	if (m->fixed) strcat (result, "fixed.\n");
    	else strcat (result, "not fixed.\n");
    	return result;
    
    }
    
    ///////////////////////////////////////////////////
    
    # c_vitro.h
    
    #ifndef C_VITRO_H_
    #define C_VITRO_H_
    
    #include <time.h>
    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define Measure struct measure
    #define Cell struct cell
    
    #define maxNameLength 			20
    #define maxDescriptionLength  100
    #define maxHtmlLength 		  1000
    
    #include "Measure.h"
    
    #endif /*C_VITRO_H_*/
    
    ///////////////////////////////////////////7
    
    #c_vitro.c
    
    #include "c_vitro.h"
    
    int main () {
    
    	Measure* m=new_measure (1, "Darth" , "Vader", "<html><b>Darth
                                                           Vader</b></html>");
    	print_measure (m);
    	delete_measure (m);
    
    	return 0;	
    }
    

    Alles wird einwandfrei compiliert und siehe da: segmentation fault ...

    Meine Güte, da waren mir die CompilerErrors doch sympathischer, da waren mehr Details drin enthalten 💡

    Aber was dieser runTimeError nun bedeutet, da habe ich nun wirklich keine Idee. Was habe ich falsch gemacht? Wenn ich den Compiler via Shell starte mit

    chess@vulcan:~/workspace/c_vitro> gcc c_vitro.c -g -o segfault

    so kommt die folgende Info:

    /tmp/ccOVVuP7.o: In function main': /home/chess/workspace/c\_vitro/c\_vitro.c:5: undefined reference tonew_measure'
    /home/chess/workspace/c_vitro/c_vitro.c:6: undefined reference to print_measure' /home/chess/workspace/c\_vitro/c\_vitro.c:7: undefined reference todelete_measure'

    Gut sage ich mir und kopiere nun den Inhalt von der Measure.c in die c_vitro.c und lösche anschließend Measure.c. Gesagt, getan.

    Jetzt funktioniert

    gcc c_vitro.c -g -o segfault

    wunderbar, bzw. ohne Fehlermeldung, nur damit wieder

    segmentation fault

    als Fehlermeldung kommt, wenn ich ./c_vitro nutze, um das Progrämmchen zu starten.

    Wo liegt das Problem?

    Danke ...

    Peilnix



  • Ich habe die char* in der Funktion print durch char[2000] ersetzt und jetzt funktioniert es ganz wunderbar. Auf jeden Fall ein Erfolgserlebnis ...

    Lass mich raten. Dynamisch geht es, wenn ich die Größe des Ausgabetextes + 1 errechne, dann mit calloc den char reserviere und abschließend wieder free befreie?!

    Das kann aber erst nach dem return statement der funktion string_measure machen ... das würde wiederum heißen, dass ich nach dem aufruf eben dieser funktion stets die funktion free aufrufe?!

    😕

    Also gibt es einen sinnvollen weg, die größe des ReturnArrays dynamisch zu bestimmen (nicht wirklich wichtig, aus reinem interesse ...)

    Grüße an alle,

    Peilnix



  • Benutz dir [cpp]-Tags (nicht die [code]-Tags) und schau, dass du sie auch richtig verwendest. So will man den Code von dir nicht gerne lesen. Du kannst deine Beiträge auch editieren.



  • Hallo Tim,

    Du hast recht, das ist so deutlich übersichtlicher. Danke für den Hinweis.

    Peilnix


Anmelden zum Antworten