메모리 처리 단위를 알고자 하면 ?
글쓴이: tombraid / 작성시간: 토, 2004/02/07 - 8:28오후
각 시스템 마다 다를꺼 같은데요.
보통 4Byte 일꺼라 생각도 들구요.
우선, 솔라리스 같은 경우 메모리 처리 단위는 어떤 헤더파일에 정의되어 있나요?
또, 오늘 작성한 코드중에 이런 부분이 있는데요.
struct abc { char *ptr; struct abc *next; }; struct abc *pa; char *tmp; tmp = malloc (sizeof(struct abc) + 10); pa = (struct abc *)(tmp + 10); pa -> ptr = tmp;
여기서 10이라고 된 부분에 4의 배수를 사용하면 에러가 안나고,
4의 배수를 쓰지 않으면 뜻하지 않은 곳에서 에러가 나더라구요.
그래서 생각한게 시스템에서 사용하는 메모리 처리 단위때문이 아닌가 하는 생각이 들었습니다.
제 생각이 맞나요?
Forums:
제 짧은 지식으로는 메모리 처리 단위라는 것이CPU의 레지스터 크
제 짧은 지식으로는 메모리 처리 단위라는 것이
CPU의 레지스터 크기와 같은 것으로 알고 있습니다.
흔히 32bit CPU니 64bit CPU니 하는것이 레지스터 크기를 기준으로 하는 것이라고 말이죠...
따라서 우리가 사용하는 보통의 컴퓨터들에서는 대부분 4byte단위로 처리가 되고
64bit CPU를 쓰는 컴퓨터에서는 8byte 단위로 처리가 되는 것이지요
malloc()에서 메모리 크기로 들어가는 인자는 크기에 상관없이 동작해
malloc()에서 메모리 크기로 들어가는 인자는 크기에 상관없이 동작해야 합니다. 4의 배수가 아니던 아니던, 시스템에서 처리하는 메모리 unit의 크기와 상관없이 동작해야만 합니다.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://cinsk.github.io/cfaqs/
다만 문제되는 것은 위 코드처럼 어떤 목적으로 쓸 포인터를 강제로 특정한
다만 문제되는 것은 위 코드처럼 어떤 목적으로 쓸 포인터를 강제로 특정한 타입으로 변경하여 쓰는 경우인데, 이는 CPU가 메모리를 다루는 방식에 따라 다릅니다. CPU가 쓰는 memory alignment를 참고로 하셔야 할 것 같습니다.
그리고 무슨 목적인지는 잘 모르겠지만 보여주신 코드와 같은 방식은 별로 좋은 스타일이 아닙니다.
struct foo {
struct foo *next;
char s[0];
};
과 같은 구조체를 만들고,
struct foo *p;
p = malloc(sizeof(struct foo) + 필요한 문자열 길이);
같은 코드가 훨씬 나을 것 같군요.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://cinsk.github.io/cfaqs/
search
keyword : 정렬제한, alignment restriction
#pragma pack 으로 바꿀 수 있는 것으로 압니다.
하지만 역시 인정받지 못하는 trick 은 쓰지 말자가 결론이죠.
..
사실 제대로 설명할 자신이 없긴 하지만,
(머리속에 있는게 쉽게 말이나 글로 바뀌질 않아서.. 글적..)
용도는 간단한 메모리 메니징을 하려는 것이구요.
default_size + sizeof (struct abc) 의 N 배에 해당하는 큰 메모리를 잡아놓고,
alloc 요청이 있을때 마다 이것을 꺼내주고 싶은겁니다.
여기서 struct abc 는 관리를 위한 심플 큐를 만드는데 사용하는 거구요.
사용중인 메모리, 사용할수 있는 메모리 나누어서 관리하면
cinsk 님이 말씀하신 방식으로 사용가능 한데요.
조금이라도 처리를 줄일려고 사용가능한 메모리만 관리하려고 하는거죠.
그래서 위와 같은 방식을 시도한 것입니다.
설명이 좀 되었나 모르겠네요.
저두 cinsk님 의견에 동의합니다.tombraid님께서 의도하시는
저두 cinsk님 의견에 동의합니다.
tombraid님께서 의도하시는 건 작은 메모리 덩어리마다 끝에다가
자신의 시작주소와 다음 메모리 주소를 관리하실려고 하는거 같은데,
님처럼 10바이트 크기로 하시게 되면,
만일, tmp의 값(주소값)이 1000번지(라면, pa는 1014번지가 되겠죠. 말씀하신것처럼 1014라는 숫자는 4의 배수가 아닙니다. 따라서, 내부적으로 4바이트 연산자 과정에서 2바이트씩 밀리게 되는 현상이 나타날 수 있습니다. 이로 인해 뜻하지 않는 영역에서 문제가 생기게 되죠.
cinsk님처럼
사용하게 되면, 구조체의 첫번째 포인터는 항상 malloc에 의해서 주어지기 때문에 alignment fault에서 벗어날 수 있습니다.
이러한 alignment문제에서 벗어나고자 할려면, linker옵션에서 자신이 사용하는 data영역(malloc으로 할당받을)에 대해서 alignment를 바이트 단위로 하셔야 하는데, malloc으로 할당될 영역은 시스템에 의해서 결정되기 때문에 사실상 불가능하죠.
cinsk님께서 권장해 주신 방법을 사용하시고, foo구조체의 next를 abc의 next로 foo구조체의 *s를 abc의 *ptr로 사용하시면 해결될거 같네요.
Re: ..
"Modern C++ Design"을 참고하세요. 거기에도 비슷한 루틴이 있습니다. (C++의 template를 100% 활용한 코드이긴 하지만요.)
http://www.aladdin.co.kr/catalog/book.asp?ISBN=8980545177
Re: 메모리 처리 단위를 알고자 하면 ?
위에껀 malloc이 어떻든 상관없이
>>pa = (struct abc *)(tmp + 10);
이코드로 인해 pa가 malloc+xx라는 숫자의 포인터를가지게되었고
pa는 struct abc *인데 struct member를 reference할려면
4byte align이 안맞아서 그렇게 된겁니다.
tmp + xx하면 당연히 xx가 4의 배수여야 pa의 시작이 4byte align이
맞을테니까요.
^^
그세 또 다른 분의 답변들이 올라와 있네요. ^^
예로든 코드의 문제점은 alignment 때문이라는 것은 잘 알았습니다.
그런데 제가 정작 궁금하게 여겼던것은..
alignment 단위도 어떤 헤더파일엔가 들어있지 않을까?
하는 것이었습니다.
그렇다면, 그 단위의 배수만큼으로 사용하면 문제가 생기지 않을것 같아서요.
그리고, 다시 코드 말인데요.. 저도 좀 안조은 모양 같다는 생각이 들긴한데,
문제만 만들지 않는다면 나름대로 잼있는것 같아서 .. ^^;;
음냐루...
리눅스는 페이지 프레임 단위로 메모리를 할당합니다.
페이지 프레임이 4kbyte단위구요.........
솔라리스두 그렇겠져....
항상 깨어있어라 ~~~
gcc 확장 키워드 중에 __alignof__ 라는 것이 있다고 합니다.
gcc 확장 키워드 중에 __alignof__ 라는 것이 있다고 합니다.
sizeof 사용하시는 것처럼 사용하시면 되겠고요.
보통 int 형이 CPU의 워드크기나 메모리 접근하는 크기와 같을테니까
__alignof__ int 를 쓰시면 되겠네요.
다만 표준이 아니니 이식성은 당연히 떨어질테구요.
댓글 달기