메모리 처리 단위를 알고자 하면 ?

tombraid의 이미지

각 시스템 마다 다를꺼 같은데요.

보통 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의 배수를 쓰지 않으면 뜻하지 않은 곳에서 에러가 나더라구요.

그래서 생각한게 시스템에서 사용하는 메모리 처리 단위때문이 아닌가 하는 생각이 들었습니다.

제 생각이 맞나요?

nangchang의 이미지

제 짧은 지식으로는 메모리 처리 단위라는 것이

CPU의 레지스터 크기와 같은 것으로 알고 있습니다.

흔히 32bit CPU니 64bit CPU니 하는것이 레지스터 크기를 기준으로 하는 것이라고 말이죠...

따라서 우리가 사용하는 보통의 컴퓨터들에서는 대부분 4byte단위로 처리가 되고

64bit CPU를 쓰는 컴퓨터에서는 8byte 단위로 처리가 되는 것이지요

cinsk의 이미지

malloc()에서 메모리 크기로 들어가는 인자는 크기에 상관없이 동작해야 합니다. 4의 배수가 아니던 아니던, 시스템에서 처리하는 메모리 unit의 크기와 상관없이 동작해야만 합니다.

cinsk의 이미지

다만 문제되는 것은 위 코드처럼 어떤 목적으로 쓸 포인터를 강제로 특정한 타입으로 변경하여 쓰는 경우인데, 이는 CPU가 메모리를 다루는 방식에 따라 다릅니다. CPU가 쓰는 memory alignment를 참고로 하셔야 할 것 같습니다.

그리고 무슨 목적인지는 잘 모르겠지만 보여주신 코드와 같은 방식은 별로 좋은 스타일이 아닙니다.

struct foo {
struct foo *next;
char s[0];
};

과 같은 구조체를 만들고,

struct foo *p;
p = malloc(sizeof(struct foo) + 필요한 문자열 길이);

같은 코드가 훨씬 나을 것 같군요.

winner의 이미지

keyword : 정렬제한, alignment restriction

#pragma pack 으로 바꿀 수 있는 것으로 압니다.

하지만 역시 인정받지 못하는 trick 은 쓰지 말자가 결론이죠.

tombraid의 이미지

사실 제대로 설명할 자신이 없긴 하지만,

(머리속에 있는게 쉽게 말이나 글로 바뀌질 않아서.. 글적..)

용도는 간단한 메모리 메니징을 하려는 것이구요.

default_size + sizeof (struct abc) 의 N 배에 해당하는 큰 메모리를 잡아놓고,

alloc 요청이 있을때 마다 이것을 꺼내주고 싶은겁니다.

여기서 struct abc 는 관리를 위한 심플 큐를 만드는데 사용하는 거구요.

사용중인 메모리, 사용할수 있는 메모리 나누어서 관리하면

cinsk 님이 말씀하신 방식으로 사용가능 한데요.

조금이라도 처리를 줄일려고 사용가능한 메모리만 관리하려고 하는거죠.

그래서 위와 같은 방식을 시도한 것입니다.

설명이 좀 되었나 모르겠네요.

yeppiguy의 이미지

저두 cinsk님 의견에 동의합니다.
tombraid님께서 의도하시는 건 작은 메모리 덩어리마다 끝에다가
자신의 시작주소와 다음 메모리 주소를 관리하실려고 하는거 같은데,

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바이트 크기로 하시게 되면,
만일, tmp의 값(주소값)이 1000번지(라면, pa는 1014번지가 되겠죠. 말씀하신것처럼 1014라는 숫자는 4의 배수가 아닙니다. 따라서, 내부적으로 4바이트 연산자 과정에서 2바이트씩 밀리게 되는 현상이 나타날 수 있습니다. 이로 인해 뜻하지 않는 영역에서 문제가 생기게 되죠.
cinsk님처럼
struct foo { 
struct foo *next; 
char s[0]; 
}; 

과 같은 구조체를 만들고, 

struct foo *p; 
p = malloc(sizeof(struct foo) + 필요한 문자열 길이); 

사용하게 되면, 구조체의 첫번째 포인터는 항상 malloc에 의해서 주어지기 때문에 alignment fault에서 벗어날 수 있습니다.

이러한 alignment문제에서 벗어나고자 할려면, linker옵션에서 자신이 사용하는 data영역(malloc으로 할당받을)에 대해서 alignment를 바이트 단위로 하셔야 하는데, malloc으로 할당될 영역은 시스템에 의해서 결정되기 때문에 사실상 불가능하죠.
cinsk님께서 권장해 주신 방법을 사용하시고, foo구조체의 next를 abc의 next로 foo구조체의 *s를 abc의 *ptr로 사용하시면 해결될거 같네요.

cdpark의 이미지

tombraid wrote:
용도는 간단한 메모리 메니징을 하려는 것이구요.

"Modern C++ Design"을 참고하세요. 거기에도 비슷한 루틴이 있습니다. (C++의 template를 100% 활용한 코드이긴 하지만요.)

http://www.aladdin.co.kr/catalog/book.asp?ISBN=8980545177

jhoonk의 이미지

tombraid wrote:
각 시스템 마다 다를꺼 같은데요.

보통 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의 배수를 쓰지 않으면 뜻하지 않은 곳에서 에러가 나더라구요.

그래서 생각한게 시스템에서 사용하는 메모리 처리 단위때문이 아닌가 하는 생각이 들었습니다.

제 생각이 맞나요?

위에껀 malloc이 어떻든 상관없이
>>pa = (struct abc *)(tmp + 10);
이코드로 인해 pa가 malloc+xx라는 숫자의 포인터를가지게되었고
pa는 struct abc *인데 struct member를 reference할려면
4byte align이 안맞아서 그렇게 된겁니다.
tmp + xx하면 당연히 xx가 4의 배수여야 pa의 시작이 4byte align이
맞을테니까요.

tombraid의 이미지

그세 또 다른 분의 답변들이 올라와 있네요. ^^

예로든 코드의 문제점은 alignment 때문이라는 것은 잘 알았습니다.

그런데 제가 정작 궁금하게 여겼던것은..

alignment 단위도 어떤 헤더파일엔가 들어있지 않을까?

하는 것이었습니다.

그렇다면, 그 단위의 배수만큼으로 사용하면 문제가 생기지 않을것 같아서요.

그리고, 다시 코드 말인데요.. 저도 좀 안조은 모양 같다는 생각이 들긴한데,

문제만 만들지 않는다면 나름대로 잼있는것 같아서 .. ^^;;

issue00의 이미지

리눅스는 페이지 프레임 단위로 메모리를 할당합니다.
페이지 프레임이 4kbyte단위구요.........
솔라리스두 그렇겠져....

항상 깨어있어라 ~~~

최종호의 이미지

gcc 확장 키워드 중에 __alignof__ 라는 것이 있다고 합니다.
sizeof 사용하시는 것처럼 사용하시면 되겠고요.
보통 int 형이 CPU의 워드크기나 메모리 접근하는 크기와 같을테니까
__alignof__ int 를 쓰시면 되겠네요.

다만 표준이 아니니 이식성은 당연히 떨어질테구요.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.