it-swarm-tr.com

"Birden çok tanım", "ilk önce burada tanımlandı" hataları

3 projem var: Sunucu, Müşteri ve Commons. Commons içinde başlık ve kaynak çiftleri oluşturmak herhangi bir soruna yol açmaz ve işlevlere hem Sunucu hem de İstemci içinden serbestçe erişebilirim.

Ancak, bazı nedenlerden dolayı Server veya Client projesi içinde ek kaynak/başlık dosyaları oluşturmak her zaman multiple definition of (...) ve first defined here hatalarına neden olur.

Örnek:

commands.h (Client projesinin kök dizininde)

#ifndef COMMANDS_H_
#define COMMANDS_H_

#include "commands.c"

void f123();

#endif /* COMMANDS_H_ */

commands.c (Client projesinin kök dizininde)

void f123(){

}

main.c (Müşteri projesinin kök dizininde)

#include "commands.h"
int main(int argc, char** argv){

}

Hatalar:

make: *** [Client] Error 1      Client
first defined here              Client
multiple definition of `f123'   commands.c

Temizlik, yeniden indeksleme, yeniden yapılanma projeleri yardımcı olmuyor. Bilgisayarı da yeniden başlatmaz.

13
matt-pielat

Buradaki sorun, fonksiyon prototipinden önce commands.ccommands.h içine dahil etmenizdir. Bu nedenle, C ön işlemcisi, fonksiyon prototipinden önce commands.c içeriğini commands.h içine yerleştirir. commands.c, fonksiyon tanımını içerir. Sonuç olarak, işlev tanımı hataya neden olan işlev bildirgesinden önce sona erer.

İşlemci öncesi aşamadan sonra commands.h içeriği şu şekilde görünür:

#ifndef COMMANDS_H_
#define COMMANDS_H_

// function definition
void f123(){

}

// function declaration
void f123();

#endif /* COMMANDS_H_ */

Bu bir hatadır çünkü C'deki tanımından sonra bir işlev bildiremezsiniz. #include "commands.c" ve işlev bildirimini değiştirdiyseniz, hata olmamalıdır çünkü işlev prototipi işlev bildiriminin önüne gelir. 

Ancak, bir .c dosyası dahil etmek kötü bir uygulamadır ve kaçınılması gerekir. Bu sorun için daha iyi bir çözüm, commands.h içinde commands.c içermek ve komutun derlenmiş versiyonunu ana dosyaya bağlamak olacaktır. Örneğin:

commands.h

ifndef COMMANDS_H_
#define COMMANDS_H_

void f123(); // function declaration

#endif

commands.c

#include "commands.h"

void f123(){} // function definition
16
Giuseppe Pes

Command.c'yi başlık dosyasına eklememelisiniz. Genel olarak, .c dosyalarını içermemelisiniz. Aksine, commands.c commands.h dosyasını içermelidir. Burada tanımlandığı gibi, C önişlemcisi commands.c'nin içeriğini include'ların bulunduğu commands.h dosyasına yerleştirmektedir. F123 komutunun iki tanımı ile bitirdiniz.

commands.h

#ifndef COMMANDS_H_
#define COMMANDS_H_

void f123();

#endif

commands.c

#include "commands.h"

void f123()
{
    /* code */
}
4
andrewrmack

Belki de .c dosyasını makefile dosyasına birçok kez dahil ettiniz. 

1
Chuanhang.gu

Bu A'yı ekliyorum çünkü bunun nedenini tespit edene kadar kafamı bir saat kadar tırmalamamı sağlayan tuhaf bir versiyonuyla yakalandım. Yüklemem bu biçimin birden fazla tekrarı nedeniyle başarısız oldu

<path>/linit.o:(.rodata1.libs+0x50): multiple definition of `lua_lib_BASE'
<path>/linit.o:(.rodata1.libs+0x50): first defined here

Makefile sihirbazımda bir hata olduğu ortaya çıktı, burada C dosyalarının bir listesi vardı ve vpath vs. kullanıyordum. Ancak, bir satırın sonunda ve bir sonrakinin başında listede bir C dosyası tekrarlandı, böylece make tarafından oluşturulan gcc yükü komut satırında .o dosyasına iki kez sahip oldu. Durrrrh. Çoklu tanımlar aynı dosyanın çoklu oluşumlarından geliyordu. Bağlayıcı statik başlatıcılardan farklı olarak kopyaları yoksaydı! 

0
TerryE