모든 재배치 가능한 오브젝트 파일들은 심볼 테이블과 그와 관련된 심볼들을 가지고 있다. 링커의 관점에서 볼 때 심볼들은 다음과 같이 분류할 수 있다.

 - 현재의 파일에서 정의되고, 다른 파일들에서 참조되는 전역 심볼. 모든 non-static 함수들과 전역 변수들이 이 분류에 해당한다.

 - 현재의 파일에서 참조는 되나, 다른 곳에서 정의된 전역 심볼. extern으로 정의된 모든 함수들과 변수들이 이 분류에 해당한다.

 - 현재의 파일에서만 정의되고 참조되는 지역 심볼. 모든 static 함수들과 변수들이 이 분류에 해당한다.

링커는 심볼의 참조를 해석할 때, 입력으로 주어지는 재배치 가능한 오브젝트 파일의 심볼 테이블로부터 꼭 하나만 존재하는 심볼의 정의를 참조하여 심볼 참조를 해석한다. 지역 심볼은 그에 대한 다중 정의를 심볼 테이블이 가질 수 없으므로 쉽게 해석 된다. 그러나 전역 심볼의 해석은 약간의 트릭이 요구된다. 컴파일 타임 때, 컴파일러는 전역 심볼들을 strong 혹은 weak 한 것으로 만드는데, 함수들과 초기화 된 전역 변수들은 strong 하게, 초기화 되지 않은 변수들은 weak하게 만든다. 그러면 링커는 아래의 룰을 적용하여 심볼들을 해석하게 된다. 

1. 다중 strong 심볼들은 허가되지 않는다.

2. 하나의 strong 심볼과 여러 개의 weak 심볼들이 있으면, strong 심볼을 선택한다.

3. 여러 개의 weak 심볼들이 있으면, 그것들 중 아무거나 선택한다.

출 처 : http://wiki.kldp.org/wiki.php/DocbookSgml/LinkerLoader-TRANS 



1. 초기화 된 전역 변수는 strong 하게, 초기화 되지 않은 변수들은 weak 하게 만든다..

- funcA.c -
1
2
3
4
5
6
7
8
#include <stdio.h>

int a = 6;          // Strong Symbol

void funcA()
{
    printf("funcA()\n");
}

- main.c -
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int a;                  // Weak Symbol

int main()
{
    printf("a = %d\n", a);
    funcA();

    return 0;
}

- 결과 화면 -




2. 2개의 초기화 된 전역 변수 (Strong Symbol) 일 때

- funcA.c -
1
2
3
4
5
6
7
8
#include <stdio.h>

int a = 6;          // Strong Symbol

void funcA()
{
    printf("funcA()\n");
}

- main.c -
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int a = 10;         // Strong Symbol

int main()
{
    printf("a = %d\n", a);
    funcA();

    return 0;
}

- 결과 화면 -


컴파일 시 에러 발생...




3. 초기화 된 전역 변수 하나를 __weak 속성을 부여 했을 때

- funcA.c -
1
2
3
4
5
6
7
8
#include <stdio.h>

int a = 6;          // Strong Symbol

void funcA()
{
    printf("funcA()\n");
}

 - main.c -
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int __attribute__((weak)) a = 10;   // Weak Symbol

int main()
{
    printf("a = %d\n", a);
    funcA();

    return 0;
}
 
- 결과 화면 -
 

초기화 된 전역 변수 2개를 선언했더라도, 2번 경우와 다르게 하나의 심볼을 weak로 지정해서 에러없이 컴파일 되며, 실행도 잘 되었다.


 

+ Recent posts