반응형




http://blog.naver.com/tipsware/100149886155






먼저 오류번호 앞에 C 가 붙어 있으면 컴파일 오류코드라는 뜻이고 LNK 가 붙어 있으면 컴파일은 성공했지만 링크(link) 작업을

하다가 생긴 오류코드라는 뜻입니다.

 

"소스파일(*.c, *.cpp)"  ->  컴파일  ->  "목적파일(*.obj)"  ->  링크  ->  "실행파일(*.exe)"

 

 

1. C2086 오류코드

 

    C/C++ 언어에서는 전역변수를  동일한 이름으로 중복해서 선언할수 없기 때문에 이와같은 컴파일 오류가 발생합니다.

   (  g_data 전역변수를 중복해서 선언하여 발생한 오류 )

    이런경우는 대부분 전역변수를 많이 사용하는 프로그래머들이 실수로 이름을 중복 사용해서 발생하며 중복된 이름을

    다른 이름으로 변경하여 오류를 수정해야합니다.

 

    int g_data;
    int g_data;   // error C2086: 'g_data' : redefinition

 

    void main()
    {

     }
 

 

2. C2084 오류코드

    

    C 언어에서는 함수를 동일한 이름으로 중복해서 정의할수 없기 때문에 이와같은 컴파일 오류가 발생합니다. C++ 에서는

    함수의 오버로딩을 사용하여 동일한 이름을 가진 함수를 정의할수 있지만 아래와 같이 동일한 이름과 동일한 매개변수 구조를

    가진 경우에는 오버로딩이 적용되지 않기 때문에 아래와 같이 오류가 발생합니다.

    ( Test 라는 함수가 같은 소스내에 중복해서 정의 되었기 때문에 발생하는 오류 )

 

    void Test()
    {
    }

 

    void Test()    // error C2084: function 'void __cdecl Test(void)' already has a body
    {
    }

 

    void main()
    {
        Test();
    }

 

 

3. LNK2005 오류코드

 

    다양한 기능을 가진 프로그램을 하다보면 하나의 소스파일로 작업하지 않고 의미있는 코드를 그룹지어 여러개의

    소스로 나누어 작업하는 경우도 많습니다. 예를들의 자신의 프로젝트가 Exam1.cpp 의 소스파일로만 구성될수도

    있지만 Exam1.cpp, Exam2.cpp 와 같이 두개의 소스 파일로 구성될수도 있습니다.

    

    프로젝트를 구성하고 있는 소스파일은 관리를 편하게 하기 위해서 나누어진것일뿐 실제로는 하나의 소스라고

    생각하시면 됩니다. 따라서 자신의 프로젝트가  Exam1.cpp, Exam2.cpp 이라는 두개의 소스 파일로 구성되어

    있고 아래와 같이 소스를 작성해보겠습니다.

 

    // Exam1.cpp

    int g_data;

    

    void main()

    {

    }

 

    // Exam2.cpp

    int g_data;

   

    void Test()

    {

    }

   

    위 예제를 컴파일해보면 각각의 소스파일에는 문제가 없기 때문에 정상적으로 컴파일되어 Exam1.obj, Exam2.obj 로

    목적파일이 만들어집니다. 하지만 두개의 목적파일을 링크하여 실행파일 만드는 과정에서 아래와 같은 오류가  

    발생합니다. 이것은 각각 소스에서 사용한 g_data 라는 전역변수가 전체 프로그램(프로젝트)에서 봤을때는 중복해서

    선언된 것이기 때문에 오류처리된 것입니다. 즉, 전역변수는 단위소스에서만 전역적으로 사용 가능한것이 아니라

    프로그램(프로젝트) 전체에서 전역적으로 사용한것이기 때문입니다.

 

    int g_data" (?g_data@@3HA) already defined in Exam1.obj

 

    이렇게 발생한 오류를 해결하는 방법은 크게 두가지 입니다.

   

   

    3.1 두개의 전역변수가 이름은 같지만 서로 다른 의미로 사용된 경우

   

        가장 간단한 방법은 둘중에 한개의 전역변수의 이름을 변경하는 것입니다. 하지만, 여러가지 이유로 이름을 변경할 수

        없는 상황이라면 아래와 같이 전역변수 앞에 static 키워드를 붙여서 사용하면 오류를 제거할수 있습니다.

        ( 중복된 두개의 전역변수중에 한군데만 static 을 사용해도 오류가 제거됩니다. )

   

        static int g_data;

 

        전역변수 앞에 static 키워드를 사용하면 해당 소스파일에서만 전역적으로 사용할수 있는 전역변수로 범위가 한정됩니다.

 

    

    3.2 두개의 전역변수가 같은 의미로 사용된 경우 ( 동일한 변수 이여야 하는 경우 )

 

        하나의 전역변수를 두개의 소스파일에서 사용하고 싶은 경우라면 한쪽을 원본으로 하고 나머지 한쪽은 참조하는 형식으로

        선언해서 사용해야 합니다. 위와 같은 경우라면 Exam1.cpp 에 선언된 g_data 전역 변수는 그대로 유지하고 Exam2.cpp 에

        선언된 g_data 전역변수 앞에 extern 키워드를 추가해서 사용하면 됩니다. 소스를 재구성해보면 아래와 같습니다.

   

        // Exam1.cpp

        int g_data;

  

        void main()

        {

         }

 

        // Exam2.cpp

        extern int g_data;

  

        void Test()

        {

         }

  

        extern 을 전역변수 선언에 같이 사용하면 전체 프로그램(프로젝트)내에 동일한 이름을 가진 전역변수가 존재하고

        그 전역변수를 이 소스파일에서 참조해서 사용하겠다는 뜻이됩니다.

   

   

    LNK2005 오류는 전역변수에서만 발생하는것이 아니라 함수도 같은 이름을 사용하면 발생합니다. ( 오버로딩이 적용 안되는 경우 )

    아래와 같이 Exam1.cpp 와 Exam2.cpp 가 하나의 프로젝트에 포함되어 있다면 각각의 소스파일은 정상적으로 컴파일 되겠지만

    링크시에

 

    void __cdecl Test(void)" (?Test@@YAXXZ) already defined in Exam1.obj

 

    이라는 오류가 발생합니다. 이것도 하나의 프로그램(프로젝트)에 동일한 이름을 가진 두개의 함수가 정의 되었기 때문에

    발생한 오류입니다.

 

    // Exam1.cpp

    void Test()

    {

    }

    

    void main()

    {

        Test();

    }

   

    // Exam2.cpp

    void Test()

    {

    }

 

    void MyFunc()

    {

         Test();

    }

 

    이 문제를 해결하려면 전역변수와 마찬가지로 두가지 해결 방법이 있습니다.

 

  

    3.3 두개의 함수가 이름은 같지만 서로 다른 의미로 사용된 경우

 

        전역변수와 마찬가지로 두개의 함수의 이름을 다르게 하거나 해당 함수앞에 static 키워드를 사용하여 사용범위를 제한하면

        오류를 해결할수 있습니다. 이때도 둘중에 한곳에만 static 을 사용하면 됩니다.

   

        // Exam1.cpp

        void Test()

        {

        }

 

        void main()

        {

            Test();

        }

  

        // Exam2.cpp

        static void Test()

        {

        }

  

        void MyFunc()

        {

            Test();   // Exam2.cpp 에 있는 Test 함수가 호출됨

        }

 

 

    3.4 두개의 함수가 동일하게 사용되어야 하는 경우 ( 양쪽 소스에서 같은 Test 함수를 호출하고 싶은 경우 )

   

        같은 프로젝트에 포함된 다른 소스에 존재하는 함수를 사용하고 싶다면 해당 함수의 원형(prototype)만 선언해주고

       사용하면 됩니다.

 

        // Exam1.cpp

        void Test()

        {

        }

 

        void main()

        {

            Test();

        }

 

        // Exam2.cpp

        void Test();    // 사용하고 싶은 함수의 원형을 명시한다.

 

        void MyFunc()

        {

            Test(); // Exam1.cpp 에 있는 Test 함수가 호출됨

        }

 

 

사실 위와 같은 경우는 소스를 수정하여 오류를 제거할수 있기 때문에 이런 오류 코드가 문제가 되지 않습니다. 정말 난감한 문제는

자신이 두개의 라이브러리(Library, *.lib)를 사용해야 하는데 각 라이브러리에 동일한 이름을 가진 함수가 있을때도 LNK2005 오류가

발생한다는 것입니다. 자신이 만든 라이브러리라면 소스를 수정해서 다시 라이브러리를 만들면 되겠지만 소스가 없는 없다면

Visual C++ 의 링크 옵션을 조절해서 해결을 해야합니다.

  

이런 경우는 상황에 따라서 대처하는 방법이 다르기 때문에 해결책을 직접적으로 알려드리기는 어려울듯합니다. 그래서

관련해서 예시가 있으니 아래에 링크해드린 자료를 한번 읽어보시기 바랍니다.

  

http://support.microsoft.com/kb/148652/ko

   

 

저는 www.tipssoft.com 사이트의 관리자이며 위 자료는 해당 사이트에도 동일하게 게시되어 있음을 알려드립니다.
www.tipssoft.com 사이트는 프로그래머들의 정보공유를 위해 제가 운영하고 있는 사이트 입니다.
  
이 게시물과 동일한 자료의 www. tipssoft.com 게시물 URI 는 다음과 같습니다.
http://www.tipssoft.com/bulletin/tb.php/FAQ/1156 )

반응형

+ Recent posts