GNU의 C에서 함수 혹은 구조체, 변수등에 컴파일러가 코드를 컴파일 할 때 특정 방향으로 컴파일 할 수 있도록 속성을 설정할 수 있는 것이 __attribute__ 이다.

GNU의 C 코드에서 간혹 __attribute__ 라고 써있는 것을 볼 수 있다.
_ 2개를 attribute 끝에 붙여서 사용한다. 그리고 그 뒤에 괄호 두개 사이에 원하는 속성을 넣으면 된다.

예로 이렇게 사용한다.
내가 how2heap의 house of spirit을 분석하다가 마주한 코드이다.

unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));

위와 같이 사용한다.
사용할 수 있는 속성은 굉장히 많다.

예로 든 aligned 속성은 메모리의 정렬 단위를 설정하는 것이다.
해당 내용은 memory alignment를 검색해보면 찾아 볼 수 있다.

간단히 설명하면 메모리에서 입출력을 할 때 가져오는 단위 WORD 로 가져오기 때문에 메모리에 값을 저장할 때 신경을 써야한다. 
예를 들어서 좋지 않은 경우를 보겠다.

32비트 컴퓨터라고 하자. 그렇다면 WORD의 단위는 4바이트이다. 그렇다면 메모리에서 4바이트 단위로 값을 가져온다.
여기서 우리가 int 의 값을 저장한다고 하자.( int 는 4바이트(word의 값))
메모리 주소 0번지 부터 저장한다 치면 주소 0,1,2,3 에 우리의 값이 적혀지게 되고
이 값을 부를 때 0번지 주소를 부르게 되면 4바이트 단위로 값을 가져오기 때문에 0,1,2,3 주소의 값을 가져오게 되어 한번의 호출로 우리가 저장한 값을 가져올 수 있다.

하지만 만약 2번지 주소에 저장되었다 치자.
그러면 2,3,4,5 주소에 우리의 int 값이 저장된다. 이 값을 호출 하기위해 메모리 주소를 2번부터 부를 수 있을까? 그렇지 않다. 32비트의 컴퓨터이므로 4바이트 단위로 메모리에서 값을 가져오기 때문에
만약 2번지 주소에 저장되어있다면
0번부터 불러서 0,1,2,3 을 부른 후, 다시 4번부터 또 불러 4,5,6,7 을 가져와서
우리가 저장했던 값을 가져온다. 즉, 메모리 호출을 2번 하게 되는 것이다. 메모리에서 값을 가져오고 쓰는 과정은 굉장히 비싼 작업이다. (시간이 오래걸린다.) 그렇기 때문에 메모리에 값을 저장할 때 신경을 써줘야한다. 보통 이 작업을 컴파일러가 알아서 해준다. 하지만 프로그래머가 특별히 어떠한 단위로 저장을 원할 경우 __attribute__의 aligned 속성을 사용해 지정해 줄 수 있다.

*  __attribute__ ((aligned(4))); 를 이용한 해결
위의 경우 2번지에 저장이 되었는데 그 앞에 char 변수 2개가 들어있는 구조체라고 하자.
그렇다면 위의 상황이 나온다. (보통 요즘의 컴파일러들이 알아서 구조체에서 가장 큰 사이즈의 단위로 alignment를 해주지만 안해준다고 치자!)
그렇다면 여기서 우리는 구조체 선언할 때 뒤에 __attribute__ ((aligned(4)));를 붙이므로써 이 문제를 해결할 수 있다.
그렇게 되면 0번지부터 char 변수 2개가 들어가고, 메모리 2,3 주소에 패딩이 들어간다.
패딩이란 메모리 단위를 맞춰주기위한 더미값? 이라고 생각하면된다.
그리고 int값을 쓸 때는 4번지 주소부터 적게 되어 아까 위의 문제가 발생하지 않게 되는 것이다.

+ Recent posts