pointer type의 casting과 관련한 질문입니다.

GunSmoke의 이미지

안녕하세요. 책을 쓴 분에게 직접 질문하면 좋겠지만 504error로 접근을 못 하겠군요.
casting과 관련한 질문입니다.

int i, *pi;
char *pc;

pi = (int *)((char *)&i);

위의 예는 pointer to int에서 1바이트로 정렬제한이 덜 엄격한 pointer to char로의 casting이기 때문에 정렬제한을 위반하지 않습니다.

char c, *pc = &c;
pc = (char *)((int *)pc);

그러나 위의 예는 pointer to char에서 pointer to int로의 casting이기 때문에 정렬제한을 위반하여 포인터 변환이 정상적으로 수행되지 않습니다.
이것이 옳은지 궁금합니다.
전웅의 이미지

GunSmoke wrote:
안녕하세요. 책을 쓴 분에게 직접 질문하면 좋겠지만 504error로 접근을 못 하겠군요.

해커가 얌전하면 귀찮아서 함께 공존을 해보려 했는데 말썽이 심해 현재
서버 밀고 다시 설치하는 중입니다. :-(

GunSmoke wrote:
casting과 관련한 질문입니다.

int i, *pi;
char *pc;

pi = (int *)((char *)&i);

위의 예는 pointer to int에서 1바이트로 정렬제한이 덜 엄격한 pointer to char로의 casting이기 때문에 정렬제한을 위반하지 않습니다.

예, 그렇습니다. 문자형 포인터는 정렬 제한과 관련된 문제를 겪지
않습니다.

GunSmoke wrote:
char c, *pc = &c;
pc = (char *)((int *)pc);

그러나 위의 예는 pointer to char에서 pointer to int로의 casting이기 때문에 정렬제한을 위반하여 포인터 변환이 정상적으로 수행되지 않습니다.

맞습니다. c 의 주소값이 pointer to int 가 가리키기에 적절하지 않도록
정렬되어 있을 수도 있습니다.

단, 표현을 더 정확하게 하자면 "정상적으로 수행되지 않을 수도 있습니다"
입니다. 단지 성능 상의 손해만을 보거나 정렬 제한에 무감각한 환경도
있습니다.

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

ㅡ,.ㅡ;;의 이미지

운영체와 컴파일러가 무엇인지 궁금하네요..
저는 위와같은코드만으로 에러나는건 못본거 같은데.


----------------------------------------------------------------------------

전웅의 이미지

ㅡ,.ㅡ;; wrote:
운영체와 컴파일러가 무엇인지 궁금하네요..
저는 위와같은코드만으로 에러나는건 못본거 같은데.

% cat buserror.c
int main(void)
{
    char c[20];
    int *pi = (int *)(c+1);

    *pi = 0;

    return *pi;
}
% gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.7/2.95.2/specs
gcc version 2.95.2 19991024 (release)
% gcc buserror.c
% ./a.out
Bus Error (core dumped)

참고로 SunOS 는 segmentation fault 와 (정렬제한 위반으로 인한) bus
error 를 구분합니다.

c 를 배열로 잡고 첫번째 요소를 변환한 이유는 빼도박도 못하고
정렬제한을 위반하도록 만들기 위해서 입니다.

명시적인 오류가 나지 않는 경우라도 성능 저하는 이런 저런 환경에서 많이
일어납니다. 물론, 프로그램의 전체 성능에 치명적인 경우는 거의
없습니다만...

[아랫 부분은 수정으로 추가합니다]

아.. 바쁘게 적느라 깜빡했습니다만, 위와 같은 경우는 명시적인 "접근"이
있어 정렬제한 위반을 가시적으로 보여주지만, OP의 예에서처럼 여러번의
포인터 변환만으로 정렬제한과 관련된 가시적인 문제를 일으키는 경우는
주로 implementation 이 잘못 정렬된 포인터의 값을 임의로 수정하는 경우
(포인터 표현에 invalid bit 를 포함하거나 수정된 값으로 mapping table
을 탐색하는 경우 포함) 입니다. 그와 관련된 구체적인 경우는 저 역시
직접 본 적은 없으나, 표준은 정렬제한을 위반하는 포인터 변환이 일어나는
시점부터 정의되지 않은 행동으로 규정하고 있습니다 - lint 가 명시적인
접근이 아닌 변환 시점에 "possble alignment restriction violation" 같은
식의 힌트를 주는 이유도 동일한 맥락으로 이해할 수 있습니다. 따라서
굳이 그와 같은 무의미한 행동을 하는 것이 득될 것은 없습니다. 예를 들어
OP가 보인 형태의 예는 표준이 다음 프로그램도 잘못된 것으로 규정하고
있는 것과 비슷한 상황으로 이해할 수 있습니다.

int *func(void)
{
    int i;

    return &i;
}

int main(void)
{
    int *pi = func();

    pi;    /* undefined behavior */
}

segmented architecture 의 경우 단순한 포인터 값 참조가 문제를 일으키는
경우를 쉽게 상상해볼 수 있지만 volatile 한정도 아닌 무의미한 참조를
있는 그대로 번역해줄 "실용적인" 컴파일러를 찾기가 쉬운 일은 아니기에
다소 학습적인 예로 볼 수 있습니다.

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

GunSmoke의 이미지

전웅 wrote:
ㅡ,.ㅡ;; wrote:
운영체와 컴파일러가 무엇인지 궁금하네요..
저는 위와같은코드만으로 에러나는건 못본거 같은데.

% cat buserror.c
int main(void)
{
    char c[20];
    int *pi = (int *)(c+1);

    *pi = 0;

    return *pi;
}
% gcc -v
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.7/2.95.2/specs
gcc version 2.95.2 19991024 (release)
% gcc buserror.c
% ./a.out
Bus Error (core dumped)

참고로 SunOS 는 segmentation fault 와 (정렬제한 위반으로 인한) bus
error 를 구분합니다.

c 를 배열로 잡고 첫번째 요소를 변환한 이유는 빼도박도 못하고
정렬제한을 위반하도록 만들기 위해서 입니다.

명시적인 오류가 나지 않는 경우라도 성능 저하는 이런 저런 환경에서 많이
일어납니다. 물론, 프로그램의 전체 성능에 치명적인 경우는 거의
없습니다만...

[아랫 부분은 수정으로 추가합니다]

아.. 바쁘게 적느라 깜빡했습니다만, 위와 같은 경우는 명시적인 "접근"이
있어 정렬제한 위반을 가시적으로 보여주지만, OP의 예에서처럼 여러번의
포인터 변환만으로 정렬제한과 관련된 가시적인 문제를 일으키는 경우는
주로 implementation 이 잘못 정렬된 포인터의 값을 임의로 수정하는 경우
(포인터 표현에 invalid bit 를 포함하거나 수정된 값으로 mapping table
을 탐색하는 경우 포함) 입니다. 그와 관련된 구체적인 경우는 저 역시
직접 본 적은 없으나, 표준은 정렬제한을 위반하는 포인터 변환이 일어나는
시점부터 정의되지 않은 행동으로 규정하고 있습니다 - lint 가 명시적인
접근이 아닌 변환 시점에 "possble alignment restriction violation" 같은
식의 힌트를 주는 이유도 동일한 맥락으로 이해할 수 있습니다. 따라서
굳이 그와 같은 무의미한 행동을 하는 것이 득될 것은 없습니다. 예를 들어
OP가 보인 형태의 예는 표준이 다음 프로그램도 잘못된 것으로 규정하고
있는 것과 비슷한 상황으로 이해할 수 있습니다.

int *func(void)
{
    int i;

    return &i;
}

int main(void)
{
    int *pi = func();

    pi;    /* undefined behavior */
}

segmented architecture 의 경우 단순한 포인터 값 참조가 문제를 일으키는
경우를 쉽게 상상해볼 수 있지만 volatile 한정도 아닌 무의미한 참조를
있는 그대로 번역해줄 "실용적인" 컴파일러를 찾기가 쉬운 일은 아니기에
다소 학습적인 예로 볼 수 있습니다.

He's back!!

大逆戰

댓글 달기

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