multiple definition 에러입니다.

study의 이미지

다음과 같은 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 가 발생하네요.

라스코니의 이미지

main()과 test() 와의 관계가 좀 애매합니다.

저라면 main.c에는 main()를 넣고 util.c에는 print_address_list (address_t *list)를, test.c에는 test(void)를 넣는 식으로 할 것 같네요.

이럴 경우 address_list[4]는 test.c에 두는 거죠.

study의 이미지

예, 말씀 하신대로 애매합니다.
지금 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 또는 test.c 어디에 있어도 상관없지요.

보통 .h에 구현부를 넣지 않습니다. 그렇다면 .c와 다른 것이 없게 되죠.

익명 사용자의 이미지

컴파일러가 정확히 어디에 multiple definition 문제가 있는지 알려주지 않던가요?

복잡한 설명은 대략 생략하고, 문제가 되는 부분은 address_list 배열입니다.

여러 소스에서 공유가 되도록 만들려면 헤더에서는 extern을 붙여 선언만 해 주고, 정의는 소스 코드 중 단 하나에서만 해 줘야 합니다.

study의 이미지

맞습니다.
컴파일러가 배열에서 문제가 생기는 걸 알려주기는 했는데요.
소스코드에 넣지 않고 할 수 있는 방법이 없을까 생각중이었요

Anti-Lock의 이미지

test()는 유닛테스트 할려고 하시는 것 같군요.

address.h 에 있는 '배열부분'은
extern address_t address_list[4];
만 적어주고
address.c 파일을 추가해서
#include "address.h"
address_t address_list[4] = {
...
};
해주시면 될거 같네요.

study의 이미지

감사합니다. 좋은 아이디어네요 ^^
그렇게 해봐야 겠습니다 ~

Anti-Lock의 이미지

사실 첫번째 댓글이 정답인거 같습니다. (test.c에 넣으라는 내용)

address_list[]는 사실상 test 하기 위해 필요한 것이며,
나중에는 다른모듈이 완성되면, address_list[] 초기화 코드(그리고 어쩌면 address_list[] 자체도)의 필요성이 없어질 것입니다.
이렇게 되면 아마도 test.c 파일의 운명?과 목적이 같을 것 같습니다.

라스코니의 이미지

회사에서 하는 프로젝트라고 하니 그냥 학교의 팀프로젝트와는 다르다고 생각하고 의견을 드리겠습니다.
data integrity가 중요한 경우 외부 소스에서 특정 데이터를 extern 으로 선언된 바대로 바로 접근하면 안됩니다.
xxx_get_address_list() 함수 등으로 객체를 읽어오는 함수를 만들어서 중앙에서 관리해야 합니다. 이 함수내에는 mutex, lock/unlock 등이 추가될 수 있겠네요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.