sysconf 및 O3의 최적화 및

namola의 이미지

#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
 
#define INVAL_FLAG      -1
 
int main()
{
  int retval;
  errno = 0;
  retval = sysconf (INVAL_FLAG);
  if (retval != -1)
    {
      printf ("sysconf succeeded for invalid flag (%i), retval=%d errno=%d\n",
              INVAL_FLAG, retval, errno);
      abort ();
    }
  else if (errno != EINVAL)
    {
      printf ("sysconf correctly failed, but expected errno (%i) != actual (%i)\n",
              EINVAL, errno);
      abort ();
    }
  else
    printf ("using invalid name\n");
 
  return 0
}

위의 코드를 다음과 같이 주고 컴파일을 하면 제대로 실행이 안됩니다.
gcc -g -O3 -Wall -o sysconf sysconf.c
O3의 경우는 최적화 옵션인데 레벨 1, 2, 3에서 제대로 실행이 안됩니다.
gcc -g -O0 -Wall -o sysconf sysconf.c
gcc -g -Wall -o sysconf sysconf.c
위의 경우에서만 양호하게 돌아 갑니다.
즉 "using invalid name" 으로 출력 합니다.
아무래도 gcc쪽 버그인거 같습니다.( 버전은 feisty fawn의 4.1.2 )
다른 분들의 생각은 어떠 하신지요?

slc의 이미지

버그가 아닐 수도 있습니다.
기억은 가물거립니다만, 실제 최적화하면 안되는 코드를 본적이 있었습니다..

그리고, 최적화 옵션 메뉴얼을 보면,, 원하는 의도와 다르게 동작할 수 있다는
설명도 있었던것 같네요..

------------------------------------------------------------
개인 메일 서버를 만들어 사용합시다..
언제부터 e-메일이 포털의 전유물이 된거지??
home

namola의 이미지

말씀 하신것 처럼 최적화 옵션의 메뉴얼을 보면 원하는 의도와 다르게 동작 할수 있다고 나옵니다.
하지만 "-O1" 옵션에서도 문제가 발생하는것은 개인적인 생각으로는 문제가 있다고 판단 됩니다.
혹시 최적화하면 안되는 코드를 알게 되시면 말씀해주세요^^

bushi의 이미지

  errno = 0;

다음 줄에
  printf("%d\n", errno);

정도 추가하면 괜찮아지네요.

... 머리 아픕니다. 상당히.

wariua의 이미지

신기해서 한번 따라가 봤습니다...

-S 옵션으로 컴파일만 한 어셈블리어 코드를 보니 정말로 "using invalid name\n"이라는 문자열 자체가 사라져 있더군요. 이게 웬 일인가 싶어서 sysconf() 대신 다른 함수를 호출하도록 해보니... 어랏, 이번엔 사라지지가 않습니다.

알고보니 sysconf() 함수의 정체가 사실은 매크로라거나, 인라인 함수였다는 스토리가 아닐까 하는 생각에 (그럴 리가...;; ) unistd.h를 살펴보니...

/* Get the value of the system variable NAME.  */
extern long int sysconf (int __name) __THROW __attribute__ ((__const__));

응? const? 이건 뭘까 싶어서 gcc 매뉴얼을 살펴보니 "__const__"는 대략 호환성을 위해 const" 대신에 쓴 것인 듯 하고, 그 속성의 의미인 즉,...

Quote:
const

Many functions do not examine any values except their arguments, and have no effects except the return value. Basically this is just slightly more strict class than the pure attribute below, since function is not allowed to read global memory.

...

아하~ 컴파일러에게 "이 함수는 전역변수에 접근하지 않아~"라고 알려주는 게 const 속성이로군요. 그렇다면 gcc에겐 죄가 없는 셈입니다. 전역변수인 errno는 0으로 설정된 후 (sysconf()를 포함해서) 아무도 접근하지 않는 게 되어 "errno != EINVAL"가 항상 참이 되고, 따라서 마지막의 else 이후는 생략이 가능하다고 판단한 것일 테니까요.

그렇다면 glibc에서 sysconf()의 구현은 어떻게 되어 있을까요? glibc 소스의 ~glibc/sysdeps/sysv/linux/i386/sysconf.c에 있는 __sysconf()는 i386에만 한정된 처리를 담당하고 나머지는 linux_sysconf()를 다시 호출해서 처리합니다.

long int
__sysconf (int name)
{
  /* All the remainder, except the cache information, is handled in
     the generic code.  */
  if (name < _SC_LEVEL1_ICACHE_SIZE || name > _SC_LEVEL4_CACHE_LINESIZE)
    return linux_sysconf (name);
 
  ...
}
 
/* Now the generic Linux version.  */
#undef __sysconf
#define __sysconf static linux_sysconf
#include "../sysconf.c"

linux_sysconf()의 정체인 즉 ~glibc/sysdeps/sysv/linux/sysconf.c에 정의되어 있는 __sysconf()인데, 마찬가지로 리눅스에 관련된 처리만 하고서 나머지는 posix_sysconf()를 호출하여 처리합니다. ~glibc/sysdeps/posix/sysconf.c를 열어 보니...

long int
__sysconf (name)
     int name
{
  switch (name)
    {
      /* Also add obsolete or unnecessarily added constants here.  */
    case _SC_EQUIV_CLASS_MAX:
    default:
      __set_errno (EINVAL);
      return -1;
 
    case _SC_ARG_MAX:
#ifdef  ARG_MAX
      return ARG_MAX;
#else
      return -1;
#endif
 
      ...
    }
}

__set_errno()는 ~glibc/include/errno.h에 다음과 같이 정의가 되어 있군요.

# define __set_errno(val) (errno = (val))

아니, 분명히 errno에 접근을 하고 있군요!!! 혹시나 해서 ~glibc/posix/unistd.h를 살펴봐도 마찬가지로 sysconf()의 선언에 "__attribute__ ((const))"가 있구요. 흠... 도대체 왜???

그런데 glibc의 ChangeLog.11 파일에 다음과 같은 내용이 있군요.

Quote:

2000-11-08 Ulrich Drepper

* posix/unistd.h: Add attribute((const)) to sysconf prototype.

* iconvdata/euc-kr.c (euckr_from_ucs4): Map 0x20a9 to \xa3dc.
(BODY from direction): Remove special handling of \x5c.
* iconvdata/EUC-KR.irreversible: Adjust for this change.
* iconvdata/testdata/EUC-KR..UTF8: Likewise.
Reported by Jungshik Shin .

오호랏~ 2000년 어느 날에 Ulrich씨께서 집어넣으신 거로군요. (그 아래에는 iconv의 한글 인코딩과 관련한 내용도 보이는군요 :-)

... 하지만 왜???

비슷한 때에 glibc 메일링 리스트에 sysconf()의 반환값 해석 방법을 물어보는 스레드가 하나 있었는데, 거기에 Ulrich씨가 댓글을 달기도 했군요. 하지만 아쉽게도 원래의 문제와 관련된 내용은 아니로군요.

자, 일단 여기까지입니다. 과연 Ulrich씨는 왜 함수 선언에 "__attribute__ ((const))"를 추가한 걸까요?

----
$PWD `date`

$PWD `date`

namola의 이미지

친절한 설명 감사드립니다.
위의 내용으로만 비추어 봤을때는 최적화 옵션에 상관없이 전역 변수에 접근하지 않는것으로 판단이
됩니다. 이미 해보셔서 아시겠지만 최적화 옵션을 주지 않으면 양호하게 실행이 됩니다.

무한포옹의 이미지

-------------------------------
이건 뭐 익명도 아니고...

-------------------------------
== warning 대부분 틀린 얘기입니다 warning ===

익명 사용자의 이미지

뜬금없이 무슨 소리예요?
왜 툭하면 익명을 걸고넘어가는지..

댓글 달기

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