multiple definition 에러입니다.
글쓴이: study / 작성시간: 월, 2020/09/21 - 11:28오전
다음과 같은 header파일을 두 군데의 C 프로그램에서 include하고 나서 multiple definition이 발생했어요
#ifndef _ADDRESS_H_ #define _ADDRESS_H_ typedef struct address_s { int16_t id; int16_t age; uint8_t name[10]; uint8_t address[20]; } address_t; address_t address_list[4] = { {1, 20, "James K.", "SEOUL, KOREA"}, {2, 20, "Laura H.", "LONDON, UK"}, {3, 19, "Alena K.", "KIEV, UKRAINE"}, {4, 33, "MICHAEL T.", "DALLAS, USA"} }; #endif /* _ADDRESS_H_ */
이 header 파일을 사용하는 두 개의 c program인데요.
하나는 main.c 이고, 또 다른 하나는 test.c 입니다.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include "address.h" void print_address_list (address_t *list) { int16_t i = 0; printf("=================== start ================== \n"); for (i = 0 ; i < 4 ; i++) { printf("id = %d \n", list[i].id); printf("age = %d \n", list[i].age); printf("name = %s \n", list[i].name); printf("address = %s \n", list[i].address); if (i != 3) printf("------------------------------------------------------\n"); } printf("=================== start ================== \n"); } int main(void) { print_address_list(address_list); return 0; }
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include "address.h" int test(void) { print_address_list(address_list); return 0; }
회사에서는 하는 프로젝트에서 생긴 질문인데요. 원래의 소스는 올릴 수가 없지만,
위에 올린 소스가 많이 단순화 했지만, 흐름은 거의 비슷합니다.
결국은 typedef structure를 header 파일에서 선언하고 ,초기화를 한후에
두 군데 이상의 C program에서 호출하면, multiple definition 에러가 발생합니다.
왜 에러가 생기는 지 이유는 알겠는데요.
이런 경우에, 다른 분들은 어떻게 해결을 하고 있는지 궁금해서 질문을 올려봅니다.
자료구조의 초기화를 c 프로그램에서 하지 않고, header 파일에 넣은 이유는
자료를 외부에서 읽어오는 부분이 아직 완성되지 않아서, 자료를 일단 header 파일에 넣은 다음
print_address_list()만 사용/시험 하기 위해서 인데요.
그러다 보니 multiple definition error 가 발생하네요.
Forums:
main()과 test() 와의 관계가 좀 애매합니다
main()과 test() 와의 관계가 좀 애매합니다.
저라면 main.c에는 main()를 넣고 util.c에는 print_address_list (address_t *list)를, test.c에는 test(void)를 넣는 식으로 할 것 같네요.
이럴 경우 address_list[4]는 test.c에 두는 거죠.
예, 말씀 하신대로 애매합니다.
예, 말씀 하신대로 애매합니다.
지금 address_list[]를 읽어오는 함수는 따로 다른 팀원이 만들고 있어서,
그걸 읽어왔다 치고, address_list[]를 헤더에다 넣고, test나 main에서 사용하도록 하려했었거든요
address_list[]를 만드는 부분은 곧 다른 함수로 대체가 될 거라서 C 코드에 넣기가 싫었는데,
그러다 보니, 더 이상하게 되는 것 같기도 하네요.
그리고, test.c는 빌드할 때 build target에 따라 포함되기도 하고, 안되기도 하거든요
그래서, address_list[]를 test.c에 둘 수는 없을 것 같아요.
애매한 문제지만 의견 말씀해 주셔서 감사합니다. ^^
address_list[]를 util.c에 넣어도
address_list[]를 util.c에 넣어도 됩니다. address_list[]를 임시로 두고 싶다고 하시면 util.c 또는 test.c 어디에 있어도 상관없지요.
보통 .h에 구현부를 넣지 않습니다. 그렇다면 .c와 다른 것이 없게 되죠.
컴파일러가 정확히 어디에 multiple
컴파일러가 정확히 어디에 multiple definition 문제가 있는지 알려주지 않던가요?
복잡한 설명은 대략 생략하고, 문제가 되는 부분은 address_list 배열입니다.
여러 소스에서 공유가 되도록 만들려면 헤더에서는 extern을 붙여 선언만 해 주고, 정의는 소스 코드 중 단 하나에서만 해 줘야 합니다.
맞습니다.
맞습니다.
컴파일러가 배열에서 문제가 생기는 걸 알려주기는 했는데요.
소스코드에 넣지 않고 할 수 있는 방법이 없을까 생각중이었요
test()는 유닛테스트 할려고 하시는 것 같군요.
test()는 유닛테스트 할려고 하시는 것 같군요.
address.h 에 있는 '배열부분'은
extern address_t address_list[4];
만 적어주고
address.c 파일을 추가해서
#include "address.h"
address_t address_list[4] = {
...
};
해주시면 될거 같네요.
감사합니다. 좋은 아이디어네요 ^^
감사합니다. 좋은 아이디어네요 ^^
그렇게 해봐야 겠습니다 ~
사실 첫번째 댓글이 정답인거 같습니다. (test
사실 첫번째 댓글이 정답인거 같습니다. (test.c에 넣으라는 내용)
address_list[]는 사실상 test 하기 위해 필요한 것이며,
나중에는 다른모듈이 완성되면, address_list[] 초기화 코드(그리고 어쩌면 address_list[] 자체도)의 필요성이 없어질 것입니다.
이렇게 되면 아마도 test.c 파일의 운명?과 목적이 같을 것 같습니다.
회사에서 하는 프로젝트라고 하니 그냥 학교의
회사에서 하는 프로젝트라고 하니 그냥 학교의 팀프로젝트와는 다르다고 생각하고 의견을 드리겠습니다.
data integrity가 중요한 경우 외부 소스에서 특정 데이터를 extern 으로 선언된 바대로 바로 접근하면 안됩니다.
xxx_get_address_list() 함수 등으로 객체를 읽어오는 함수를 만들어서 중앙에서 관리해야 합니다. 이 함수내에는 mutex, lock/unlock 등이 추가될 수 있겠네요.
댓글 달기