LINUX.ORG.RU

inline функция: помогите понять кое-что


0

0

Копирую оригинал доков, чтобы не быть голословным.

Each fix-mapped linear address is represented by an integer index defined in the enum
fixed_addresses data structure:
enum fixed_addresses {
FIX_APIC_BASE,
FIX_IO_APIC_BASE_0,
[...]
__end_of_fixed_addresses
};
Fix-mapped linear addresses are placed at the end of the fourth gigabyte of linear
addresses. The fix_to_virt( ) function computes the constant linear address starting
from the index:
inline unsigned long fix_to_virt(const unsigned int idx)
{
if (idx >= _ _end_of_fixed_addresses)
__this_fixmap_does_not_exist( );
return (0xffffe000UL - (idx << PAGE_SHIFT));
}
Let's assume that some kernel function invokes fix_to_virt(FIX_IOAPIC_BASE_0).
Since the function is declared as "inline," the C compiler does not invoke fix_to_virt( ),
but just inserts its code in the calling function. Moreover, the check on the index value is
never performed at runtime. In fact, FIX_IOAPIC_BASE_0 is a constant, so the compiler
can cut away the if statement because its condition is false at compile time. Conversely, if
the condition is true or the argument of fix_to_virt( ) is not a constant, the compiler
issues an error during the linking phase because the symbol __this_fixmap_does_not_exist is not defined elsewhere. Eventually, the compiler
computes 0xffffe000-(1<<PAGE_SHIFT) and replaces the fix_to_virt( ) function
call with the constant linear address 0xffffd000.

Т.е., коротко говоря, компилер отрежет вызов __this_fixmap_does_not_exist().

А вот не получается у меня мой тестовый пример. См. ниже.

// inline.cpp

inline int mytest(const int i)
{
    if (i > 3)
        __bad_i();
    return i;
}

int main()
{
    int a = mytest(2);
}

Делаю gcc -O inline.cpp -o inline

Получаю:
/tmp/ccgxcQIG.o(.text+0x14): In function `mytest':
inline.c: undefined reference to `__bad_i'
collect2: ld returned 1 exit status

Вопрос: где же истина? Может быть, я что-то не так делаю?

RomanU
() автор топика
Ответ на: комментарий от RomanU

Попробую объяснить получше.
Исходя из текста выше, компилятор оптимизирует код inline функции,
не вставляя заведомо ложные условия.
Когда я читал эти доки, то усомнился в том, что там написано.
Решил проверить, как это можно написать в коде вызов функции, которая
нигде не определена, и это ещё будет компилиться.
Получил ошибки линковки.

Однако, книжка серьёзная (Understanding the Linux kernel, 2nd ed.), 
не должно быть таких грубых ошибок.

В моём примере if (i > 3) - заведомо ложное условие, потому как i при вызове = 2.

Может быть, дело в версии компилятора?

RomanU
() автор топика
Ответ на: комментарий от RomanU

Да, в исходниках ядра всё это используется.
Видимо, я создаю неправильные условия для опыта:)
objdump показывает, что действительно исчезает вызов функции __bad_i
при ложном условии. Ладно, пусть так .... :)

RomanU
() автор топика
Ответ на: комментарий от RomanU

[...]
_____static_____ inline int mytest(const int i)
{
    if (i > 3)
        __bad_i();
    return i;
}
[...]

добавь static - и все чудесным образом работает :)

anonymous
()
Ответ на: комментарий от anonymous

спасибо, не заметил, что в ядре static.
В книжке просто не было.

RomanU
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.