[완료] c++에서 inline 함수의 제약...

superwisdom의 이미지

c++에서 함수를 inline으로 처리해달라고 컴파일러에게 부탁했을 때, 함수가 인라인 함수를 재귀호출하거나, loop가 있거나, goto 등이 있는 등.. 컴파일러가 부적절하다고 판단하면 인라인 무시하잖아요?
그런데, 아무리 인라인을 무시하는 상황(for, switch, goto, 재귀호출 등)을 연출해도 gcc가 인라인으로 처리합니다. 이해가 안가서요...

물론 컴파일러에 따라서 인라인을 할 수 없는 몇몇 제약을 극복할 수는 있다고 하지만,, 제가 테스트 해보니 너무 잘 극복합니다.

예를 들어 아래의 코드(재귀호출)를 컴파일해도 인라인으로 처리됩니다.
for, switch, goto 마찬가지구요.

#include <iostream>
 
class wisdom
{
public:
    int test(int start)
    {
        start++;
        if ( start < 100 )
        {
            return test(start);
        }
        return start;
    }
};
 
int main(void)
{
    wisdom c;
    std::cout << c.test(1) << std::endl;
    return 0;
}

참고 : gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44)
컴파일 조건 : g++ -std=c++98 -pedantic -Wall -Winline -O0 wisdom.cpp

제가 뭘 잘못생각하고 있을까요?

winner의 이미지

뭘 보고?

superwisdom의 이미지

1. inline 키워드를 사용하지 않더라도 클래스 선언 안에 정의하면 그 메서드는 인라인으로 처리하려고 할테니까요. ㅋ
2. 그리고, 위에서 설명했듯이 인라인이 되지 않았을 경우 경고를 해주라는 의미에서 컴파일 시 -Winline 옵션을 주었는데, 아무런 경고도 나오지
않았기 때문에 인라인 되었다고 생각한 것입니다.
3. 어셈코드를 보더라도 인라인 되어 있었습니다. (인라인 하지 않도록 처리한 동일한 프로그램과 - 즉 inline 키워드만 뺀 - 비교)

chadr의 이미지

tail recursion의 경우에는 컴파일러가 loop로 최적화가 가능합니다.
그리고 loop는 인라인이 가능합니다. 못할 이유는 없지요.

tail recursion이 아닌 경우를 한번 테스트 해보세요.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

superwisdom의 이미지

음.. 그래서 제가 적은 컴파일 옵션을 보시면 아시겠지만, 최적화 하지 말라고 -O0 옵션도 줬는데요.. ㅠ.ㅠ
그리고 quick sort를 대략 recursive로 구현해 보아도... 인라인 함수 두개를 연산하는 또다른 인라인 함수를 만들어 보아도.. 여전히 됩니다.

근데, 컴파일러가 판단시 복잡하거나(loop등) 거대한 함수는 인라인으로 안한다로 알고 있는데요, 요즘 컴파일러는 너그러운 대인배 인가요?

참고로, "꼭 인라인 해야겠다"를 원하는건 아니구요, 단지 제가 알고 있는 인라인에 대한 이해가 어디까지 잘못되었는지 궁금해서 질문을 올렸습니다. ^^

chadr의 이미지

어디까지나 추측이지만 프로그래머가 인라인을 하라고 지시 했기 때문에 최대한 프로그래머가 하라는데로 하는게 컴파일러의 몫입니다.

만약에 인라인을 하라고 하지 않았다면 재귀호출로 컴파일을 하겠지만 인라인이 우선시 되어 가능한 인라인이
되는 형식으로 컴파일을 하지 않았을까 하는 생각이 듭니다.

사실 뭐 인라인이 강제 사항도 아니고 또한 하지 말라는 것도 표준에 정해진게 없으니(없다고 알고 있습니다.)
최대한 프로그래머의 의도에 맞춰서 어셈코드를 생성해 주는게 우선시 되므로 저런 경우에는 인라인이 되는게
맞지 않나 싶습니다.

여튼 알려진 사실과 같이 특정 상황에 대해서는 인라인을 하지 않는건 맞습니다. 하지만 이와 같은 상황에서는 최적화 옵션과 인라인 키워드가 서로 배타적이게 됩니다. 따라서 인라인이 가능한 경우라면 최적화 옵션과 관계없이 프로그래머가 지시한 문법 키워드를 최대한 따르는게 우선시 된것 같습니다.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

bootmeta의 이미지

무조건 inline 무시되지 않나요? ( inline keyword, class body 내 선언 여부와 상관없이)
무시되고 inline 시도를 하지 않았기 때문에 -Winline도 경고를 주지 않을 것 같군요.

제가 test해 본 결과 (-S나 objdump로 assembly code 출력 후 확인)
-O0는 inline되지 않았고, -O2는 inline되었습니다.

gcc manual을 보시면 알다시피, 인라인 여부는 명확한 것이 아니라, 특정 상황에서 인라인 되지 않을 가능성이 높다.로 이해해야겠죠.
(goto의 경우도 무조건 안되는 것이 아니라, non-local goto의 경우 가능성이 높음으로)
아시고 계시는 것처럼 compiler에 따라(option따라) 천차만별이니 inline된다고 가정하지 않는 것이 정신 건강에 좋겠죠.
심지어 gcc의 경우 static으로 선언되지 않은 inline 함수는 inline되더라도 compile된 함수는 남아 extern으로 참조(함수 호출)도 가능합니다.

http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Inline.html

test 환경)
gcc (Ubuntu 4.3.3-5ubuntu4) 4.3.3 / ubuntu 9.04

superwisdom의 이미지

아하.. 제가 바보같이... -O0를 붙이면 인라인 무시된다는 사실을 깜빡했네요...ㅋ

winner의 이미지

저도 간만에 -S 로 assembly를 봤습니다. Compiler 최적화가 상당하더군요. Loop unrolling과 tail recursion 제거하는 것을 눈으로 확인한 것은 처음이었거든요.

하지만 제가 해본 바에 의하면 -O2 를 넣지 않은 이상 call이 들어가 있었습니다.
아마도 -Winline 을 통해 inline이 되지 않았다는 경고가 나오지 않으니까 inline이 안 되었을거라고 생각하신지 모르겠네요. 이유는 모르겠습니다만 -O0과 -O1은 call 이 남아있는데도 경고가 나오지 않았습니다. 저는 -Winline 은 처음 봐서 잘 되는 기능인지 모르겠습니다만 gcc.gnu.org에 검색을 해보니
http://gcc.gnu.org/ml/gcc-bugs/2009-09/msg00619.html
이런 글이 있습니다.

제가 시험해본 compiler version은 (GCC) 4.1.2 20070925 (Red Hat 4.1.2-33) 입니다.

제 생각에 QuickSort는 인라인을 절대 할 수 없을텐데요. 엽기적으로 만들지 않는 이상 말이죠.

superwisdom의 이미지

감사합니다.
-Winline 옵션을 주면, 인라인 하지 못한 경우에 대해서 warning을 남길 줄 알았는데, 어찌된 이유에선지 warning message를 남기지 않아서 제가 오해했었습니다. 즉 저는 "warning이 안나고 있으면 인라인 되었구나"라고 생각한 것입니다.

위에서 제가 예를 든 코드는 실제로 인라인 되지 않고 있었습니다. (다른 윗분들과 달리, 전 -O2로 최적화 해도 인라인 안되더군요)
컴파일 : g++ wisdom.cpp -S -Wall -Winline -O2

...(생략)
main:
.LFB1439:
    subq    $24, %rsp
.LCFI1:
    movl    $2, %esi
    leaq    23(%rsp), %rdi
    call    _ZN6wisdom4testEi
...(생략)

대신 간단한 loop 정도는 inline 되어서 call 되지 않고 있음을 확인하였습니다.

결론적으로 -Winline 옵션으로는 인라인 되었는지에 대한 여부를 알 수 없겠네요.
왜 -Winline 옵션이 동작 안하는지는.... 나중에 알게 되면 이곳에 덧글 남기겠습니다. ^^

댓글 달기

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