Някак си нарушавам правилото за една дефиниция

Получавам грешки с линкера като:

osd.o(.ndata+0x514):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\osd.c: multiple definition of `video_buff_vis_num'
main.o(.ndata+0x0):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\main.c: first defined here
osd.o(.ndata+0x515):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\osd.c: multiple definition of `video_buff_draw_num'
main.o(.ndata+0x1):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\main.c: first defined here
osd.o(.ndata+0x516):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\osd.c: multiple definition of `vid_format'
main.o(.ndata+0x2):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\main.c: first defined here
osd.o(.ndata+0x518):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\osd.c: multiple definition of `vid_line'
main.o(.ndata+0x4):C:\Documents and Settings\Thomas\My Documents\PIC\dsPIC33FJ128GP802\On Screen Display\main.c: first defined here

Това ме притеснява, защото в изходния код съм включил предпазители около единственото място, откъдето могат да дойдат тези дефиниции.

#ifndef OSD_H 
#define OSD_H 

// code here, including definitions for the above

#endif // OSD_H 

Това ми лази по нервите. Почистих, възстанових и опитах отново. Дори започнах нов проект от нулата със същите файлове и получавам точно същия проблем! Някой би ли ме просветлил защо това не работи! :)

Компилиране с PIC-GCC v3.23 (версия на GCC за PIC24F/H и dsPIC30F/33F микроконтролери.)

Кажете ми, ако някой иска да види източниците на още файлове. Не исках да претрупвам тази страница.


person Thomas O    schedule 19.07.2010    source източник
comment
Декларациите влизат в .h файлове, дефинициите влизат в .c файлове.   -  person Paul R    schedule 19.07.2010


Отговори (2)


Ако включите този хедър в повече от 1 .c файл, ще имате множество дефиниции. И вие имате main.c и osd.c.

.h е правилното място за функции и декларации на extern данни. Но за променлива ще трябва да изберете един от изходните файлове. пазачите на #defined не променят това.

Вижте също този въпрос. И този отговор описва стандартния модел.

И още малко обяснение/анализ:

1) Всеки .c изходен файл се компилира независимо. Пазачите предпазват само от четене на заглавен файл два пъти по време на 1 компилация.

2) Грешката, която получавате, е грешка на линкер (не компилатор).

Когато вашият хедър дефинира променлива, компилаторът ще я третира като дефиниция при всяко отделно изпълнение. Линкерът ще открие множеството екземпляри.

person Henk Holterman    schedule 19.07.2010
comment
Да, включването на пазачи няма да помогне тук. - person Peter G.; 19.07.2010
comment
И така, как мога да избегна този проблем? Трябва да имам дефинициите на osd.h в някои от моите файлове. - person Thomas O; 19.07.2010
comment
Благодаря. Тогава ще преместя моите променливи в main.c. Все пак би изглеждало по-подходящо да ги поставя в osd.c, мога ли да го направя? Благодаря за бързата реакция! Трябваше да попитам тук, преди да прекарам 3 часа в разглеждане на целия си код. Но мога ли да попитам защо включването на предпазители се проваля тук? Със сигурност OSD_H се дефинира и след това всичко е наред, няма да се включи отново? - person Thomas O; 19.07.2010
comment
.h е правилното място за деклариране на функции. Реализациите на функциите (с изключение на вградените) също трябва да бъдат в .c файлове. @Thomas, включен е по един на .c файл. След това обаче линкерът свързва всички получени .o файлове заедно, откъдето възниква проблемът. - person Matthew Flaschen; 19.07.2010
comment
@Thomas Компилаторът компилира всеки изходен файл поотделно и след това ги свързва. Предпазителите за включване предотвратяват включването на една и съща заглавка два пъти по време на компилирането на един изходен файл, но той все още се обработва веднъж за всеки изходен файл, който го включва (директно или непряко). - person Tyler McHenry; 19.07.2010
comment
Всички изглеждат променливи. Имам няколко вградени функции. Няма статичен. Странно, изглежда, че PIC-GCC никога не вгражда нищо... може би поради ограниченията на ROM пространството, но това е въпрос за друг ден. Благодаря на всички. Ще маркирам това като приет отговор, когато ми позволи (казва, че трябва да изчакам 2 минути.) - person Thomas O; 19.07.2010
comment
Можете да поставите променливите където пожелаете, стига да се показват само в един изходен файл. Ако други изходни файлове трябва да използват тези променливи, трябва да им се даде extern декларация за променливата, евентуално в .h файл. - person Tyler McHenry; 19.07.2010

Какво съдържа включващият ви файл?

 int video_buff_vis_num;
 extern int video_buff_vis_num;

Първото или второто? Първият не дефинира променливата, но разпределя памет за нея, докато вторият просто казва „някъде има променлива с това име“.

Трябва да имате само едно място, където е разпределено, но можете да имате много дефиниции.

person Aaron Digulla    schedule 19.07.2010