LNK2005, alles richtig gemacht? Include Problem?
-
Hallo,
beim Linken kommt immer der LNK2005 Fehler. Bin eigentlich der Meinung das alles OK sein müsste. Vielleicht koennt Ihr mal einen Blick drauf werfen.
Vielen Dank
// kalender.c #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #include "typen.h" #include "funktionen.h"
// typen.h #ifndef TYPEN_H #define TYPEN_H #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> ... #endif
// funktionen.h #ifndef FUNKTIONEN_H #define FUNKTIONEN_H #include "typen.h" ... #endif
// funktionen.c #include "funktionen.h"
-
VC Hilfe schrieb:
A header file declared and defined a variable. Possible solutions include:
Declare the variable in .h: extern BOOL MyBool; and then assign to it in a .c or .cpp file: BOOL MyBool = FALSE;
...Brauchst Du die "typen.h" in "funktionen.h" wirklich?
Sonst zeig mal mehr Code, bitte.
-
naja, was heißt brauchen, aber der übersichtlichkeit halber, wollte ich es strukturieren:
LNK - Fehler bei :
alender.obj : error LNK2005: _pRun already defined in functionen.obj
kalender.obj : error LNK2005: _pOld already defined in functionen.obj
kalender.obj : error LNK2005: _pNew already defined in functionen.obj
kalender.obj : error LNK2005: _pfirst already defined in functionen.obj
kalender.obj : error LNK2005: _pHead already defined in functionen.obj
Mehr Kot:// kalender.c #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #include "typen.h" #include "funktionen.h" int main() { //noch leer }
//typen.h #ifndef TYPEN_H #define TYPEN_H #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 200 #define MAXDATECHARS 10 #define MAXTIMECHARS 5 #define TRUE 1 #define FALSE 0 #define DATEI test.dat struct datum_ { short int min; short int hours; short int day; short int month; short int year; }; typedef struct datum_ Datum; struct kalender_ { char Text[MAXCHARS]; Datum datum; struct kalender_ * Next; // kalender_ * next; }; typedef struct kalender_ Kalender; // Zeiger für die verkettete Liste Kalender *pHead = NULL; Kalender *pfirst = NULL; Kalender *pNew = NULL; Kalender *pOld = NULL; Kalender *pRun = NULL; #endif
#include "funktionen.h" // Auswahl abfragen //----------------------------------------------------------- void selectTask(char auswahl) { // char text[MAXCHARS]; if(auswahl == 1) { // printf("\nText:"); // scanf("%s",text); // printf("Zeit:"); //TimeToStruct // scanf("%s",zeit); // scanf("%s",datum); // newDate(text,zeit,datum); } else if(auswahl == 2) { printCalender(); } } // Ausgabe Menu //----------------------------------------------------------- void printMenu(void) { printf("Bitte treffen Sie eine Auswahl\n"); printf("1) neuen Termin einlesen \t 2) Termine anzeigen\n"); printf("3) Kalender neu laden \t 4) gesamten Kalender loeschen\n"); printf("5) einzelnen Termin loeschen \t\t 6) speichern und exit\n"); printf("Auswahl:"); } // neuen Termin anlegen //----------------------------------------------------------- void newDate(char * text,Datum * datum){ // pOld = pNew; pNew=(Kalender*)calloc(1,sizeof(Kalender)); copyDate(&pNew->datum,datum); strcpy(pNew->Text,text); pNew->Next = NULL; if(pHead!=NULL) pOld->Next = pNew; else pHead = pNew; }; // Kalender ausgeben //----------------------------------------------------------- void printCalender(void) { int n = 1; sortCalender(); pRun = pHead; while (pRun != NULL) { printf("Termin %i:%i.%i.%i,%i:%i...%s\n",n++,pRun->datum.day,pRun->datum.month,pRun->datum.year,pRun->datum.hours,pRun->datum.min,pRun->Text); pRun=pRun->Next; } } // Kalender sortieren //----------------------------------------------------------- void sortCalender(void) { int year1 = 0; int year2 = 0; int month1 = 0; int month2 = 0; int day1 = 0; int day2 = 0; int h1 = 0; int h2 = 0; int min1 = 0; int min2 = 0; pRun = pHead; while (pRun != NULL) { if (pRun->Next != NULL) { if (year1 == year2) { if (month1 == month2) { if (day1 == day2) { if (h1 == h2) { if (min1 == min2) { } else if (min1>min2) { // swap(pRun,pRun->Next); } } else if (h1>h2) { // swap(pRun,pRun->Next); } } else if (day1 > day2) { // swap(pRun,pRun->Next); } } else if (month1 > month2) { // swap(pRun,pRun->Next); } } else if (year1 > year2) { // swap(pRun,pRun->Next); } } pRun = pRun->Next; } } // Datum kopieren //----------------------------------------------------------- void copyDate(Datum * date1, Datum * date2) { date1->year = date2->year; date1->month = date2->month; date1->day = date2->day; date1->hours = date2->hours; date1->min = date2->min; } void TimeToStruct(char * s, Datum * datum) { datum->hours = 0; datum->hours += (s[0]-48)*10; datum->hours += (s[1]-48); }
// funktionen.h #ifndef FUNKTIONEN_H #define FUNKTIONEN_H #include "typen.h" void selectTask(char); void newDate(char *, Datum * ); // neuen Termin anlegen void saveCalendar(void); // Kalender speichern void loadCalendar(void); // Kalender laden void deleteCalendar(void); // Kalender löschen void printCalender(void); // Kalender ausgeben void sortCalender(void); // Kalender sortieren void deleteDate(void); // Termin löschen void printMenu(void); // Menu anzeigen //void swap(Kalender *, Kalender *); void copyDate(Datum *, Datum *); void TimeToStruct(char *,Datum *); #endif
-
Hab jetzt noch nicht den Überblick aber in der funktionen.h brauchst Du typen.h nicht, eine Vorabdeklaration reicht aus, wenn Du nur Zeiger benutzt. Includen kannste dann in der .c Datei.
// funktionen.h #ifndef FUNKTIONEN_H #define FUNKTIONEN_H struct kalender; void selectTask(char); void newDate(char *, Datum * ); // neuen Termin anlegen void saveCalendar(void); // Kalender speichern void loadCalendar(void); // Kalender laden void deleteCalendar(void); // Kalender löschen void printCalender(void); // Kalender ausgeben void sortCalender(void); // Kalender sortieren void deleteDate(void); // Termin löschen void printMenu(void); // Menu anzeigen //void swap(Kalender *, Kalender *); void copyDate(Datum *, Datum *); void TimeToStruct(char *,Datum *); #endif
-
ja das würde gehen, aber leider noch keine Lösung, ich warte gespannt
-
hat denn keiner eine Lösung für mein Problem? Vielleicht könnt Ihr einfach mal meinen Code bei Visual übernehmen? Zickt er dann auch rum?
Bei alten Projekten von mir ging es ja auch. Ich habe mich schon gefragt, ob irgendwelche Linker oder Compilereinstellungen verändert wurden
Viele Grüße
Filip
-
Ja was läuft wohl schief? Die Fehlermeldungen sagen es bereits...
pRun
beispielsweise wurde in "typen.h" definiert. Wenn typen.h mehrmals eingebunden wird (was hier zweifelsohne der Fall ist - einmal in "kalender.c" und ein weiteres Mal in "funktionen.c"), funktioniert das Kompilieren selbstverständlich, denn pro kompilierter Datei wurde "typen.h" nur einmal eingebunden. Werden dann aber vom Linker alle .obj-Files zusammengebunden, kommen aus den einzelnen Objektdateien mehrere Einbindungen von "typen.h", was zur Folge hat, dasspRun
mehrfach definiert wird (-> darum auch ein Linker- und kein Compilerfehler).Um das Problem zu beheben, müssen
pRun
und ähnliche in eine "typen.c" geschrieben werden und in "typen.h" alsextern
vermerkt werden. Dann sollte es gehen.
-
proggaholic schrieb:
Wenn typen.h mehrmals eingebunden wird (was hier zweifelsohne der Fall ist - einmal in "kalender.c" und ein weiteres Mal in "funktionen.c"), funktioniert das Kompilieren selbstverständlich...
Aber ich denke #ifndef verhindert ein doppeltes Einbinden?
MfG Filip
-
Äh...
Ja klar, natürlich. Hab nicht genau genug hingesehen. Allerdings sind Definitionen in header-files eigentlich nicht erlaubt...
-
also.... es funktioniert, danke an alle die geholfen haben. Aber wieso vielleicht kann mir trotzdem noch einer erklären, warum #ifndef nicht vor doppelter definition schützt?
-
Hat das Auslagern in .c geholfen?
Falls ja, liegt es daran, dass
#ifndef
eine Präprozessordirektive ist. Der Präprozessor wird beim Kompilieren als allererstes aufgerufen (noch vor Compiler/Linker/Debugger). Dadurch wird lediglich verhindert, dass "typen.h" mehrmals in "kalender.c" und "funktionen.h" eingebunden wird (d.h. man kann zwar mehrmals#include
machen, aber alle ausser dem ersten werden ignoriert). Wenn dann der Linker dran ist, wurde der include-Guard (#ifndef
) bereits abgearbeitet, und stellt plötzlich fest, dass die Definitionen doppelt vorkommen. D.h. der include-Guard hat seine Arbeit schon längst getan, sodass er beim Linken nicht mehr greift und dadurch doppelte Definitionen Fehler werfen (was in gewisser Weise ja auch gut so ist).