arm-linux-gcc의 독특한 sturct align 방식

jsoop의 이미지

arm-linux-gcc를 사용하다 x86 gcc 및 VC 와 다른 이상한 현상을 발견하여 도움을 부탁드립니다.

#include <stdio.h>

typedef struct _foo1 {
    char c1;
    char c2;
    char c3;
} foo1;

typedef struct _foo2 {
    char c1;
    char c2;
    char c3;
} foo2;

typedef struct _foo3 {
    int   i1;
    foo1  s1;
    foo2  s2;
    int   i2;
} foo3;


int main(int argc, char *argv[])
{
    foo3 s3;

    fprintf(stderr, "0x%08x\n", &s3.i1);
    fprintf(stderr, "0x%08x\n", &s3.s1);
    fprintf(stderr, "0x%08x\n", &s3.s2);
    fprintf(stderr, "0x%08x\n", &s3.i2);

    return 0;
}

이 코드의 결과는 arm-linux-gcc 와 x86 gcc 에서 다르게 나타납니다.

--- x86
0x0012ff70
0x0012ff74
0x0012ff77 <<
0x0012ff7c

-- arm
0x0012ff70
0x0012ff74
0x0012ff78 <<
0x0012ff7c

이상에서 보듯 struct 내에 다른 struct가 포함되어 있을 때 포함된 struct의 멤버가 모두 char일 경우 arm-linux-gcc는 x86 gcc 나 VC와 달리 무조건 4-byte로 align을 하고 있습니다.
어찌보면 이렇게 하는 것이 오히려 맞는 것 같기도 합니다.

- arm-linux-gcc를 사용할 경우 위와 같은 경우에 "코드를 수정하지 않고" x86 gcc와 같은 작동을 하도록 하는 옵션이 있을까요?

- "코드를 수정하는 방법으로" struct에 __atribute__ (packed()) 를 사용해 보았지만 변화가 없었습니다. 제가 제대로 사용하지 못했는지도 모르겠습니다.
혹시 가능하다면 위 코드에 맞게 수정해 주시면 고맙겠습니다.

감사합니다.

liongo의 이미지

' 형식이 내용을 규정한다. '

jsoop의 이미지

답변 감사합니다.
알려주신 문서는 이미 보았습니다.
그러나 제가 제기한 문제는 일반적인 struct alignment 와는 좀 다른 것 같습니다.
요지는 "어떤 struct 내부에 포함된 (홀수개의 char 멤버를 갖는) 다른 struct를 바깥 struct의 멤버로 생각하느냐" 하는 것입니다.
처음 글에서와 같이 arm에서는 struct를 하나의 멤버로 취급해 align을 하는 반면 x86에서는 struct의 멤버가 모두 char이기 때문에 죽 나열하고 있다는 것입니다.

aqwerf의 이미지

typedef struct _foo3 {
    int   i1;
    foo1  s1;
    foo2  s2;
    int   i2;
} __attribute__((packed)) foo3;

처럼 쓰면 동일하게 될 겁니다. __attribute__ 의 위치도 중요합니다. 다른 위치에 써도 에러는 안나지만 실제로 packed가 안되는 경우도 있던것 같던데..

다른 CPU에 비하여 ARM core의 경우 memory 참조 시 alignment가 상당히 중요합니다. RISC이다 보니 alignment가 안된 memory access시에는 exception이 발생하여 버립니다.

일반 CPU의 경우 pack을 해서 int, short가 alignment가 안된 경우에는 참조시 그냥 performance만 떨어지지만, ARM에서는 exception이 발생해 버립니다. 그래서 packed option을 사용한 경우에는 compiler가 구조체를 참조하는 부분에 code를 추가해서 access 하기 때문에 performance penalty 가 더욱 큽니다.
특히
foo3 *p;
와 같이 pointer 연산은 더욱 늦어지게 됩니다. 전역변수라면 align을 컴파일러가 예측을 할 수 있기 때문에 좀 낮지만 pointer의 경우에는 어디로 mapping될지 모르기 때문에 매번 address의 align 관계를 software적으로 check를 하고 적절한 access가 되도록 처리됩니다.

Alignment가 고려되어 있지 않은 Network packet을 받는 다는 등의 반드시 사용하여야 하는 부분이 아닌 경우에는 가능한 사용하지 않는게 좋죠.

자세한 것은 ARM 관련 site를 찾아보면 자세히 설명이 되어 있습니다.
http://www.aleph1.co.uk/armlinux/book/afaq.html
http://www.handhelds.org/z/wiki/Porting%20Software%20to%20ARM%20Linux

댓글 달기

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