Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Статическа линковка inline функций, аномалия 
V
    Опции темы
Леопольд
Дата 19.6.2009, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Демонстарционный код был изменён в сторону большей наглядности. 
Перед вызовом deleg переменная var из единицы трансляции где определенна функция main приобретает значение 1
Непосредственно после вызова deleg, переменная var получает значение 2 в той единице трансляции в которой определенна функция deleg.

Никак не могу понять следующую аномалию

test.h
Код

#ifndef TEST_H
#define TEST_H

#include <iostream>

static int var = 0;

void deleg(void);

int dyn_func(void);

static int sta_func(void){
    return var;
}

inline int inl_func(void){
    return var;
}

static inline int sta_inl_func(void){
    return var;
}

#endif


test.cpp
Код

#include "test.h"

int main(int argc, char* argv[])
{
    var = 1;
    deleg();
    std::cout<<std::endl;

    std::cout<<"var in main { dyn_func } = "<<dyn_func()<<std::endl;
    std::cout<<"var in main { sta_func } = "<<sta_func()<<std::endl;
    std::cout<<"var in main { inl_func } = "<<inl_func()<<std::endl;
    std::cout<<"var in main { sta_inl_func } = "<<sta_inl_func()<<std::endl;
}


second.cpp
Код

#include "test.h"

int dyn_func(void){
    return var;
}

void deleg(void){
    var = 2;
    std::cout<<"var in deleg { dyn_func } = "<<dyn_func()<<std::endl;
    std::cout<<"var in deleg { sta_func } = "<<sta_func()<<std::endl;
    std::cout<<"var in deleg { inl_func } = "<<inl_func()<<std::endl;
    std::cout<<"var in deleg { sta_inl_func } = "<<sta_inl_func()<<std::endl;
}


результат (сборка VC 2005)
Код

var in deleg { dyn_func } = 2
var in deleg { sta_func } = 2
var in deleg { inl_func } = 1
var in deleg { sta_inl_func } = 2

var in main { dyn_func } = 2
var in main { sta_func } = 1
var in main { inl_func } = 1
var in main { sta_inl_func } = 1


Почему var in deleg { inl_func } = 1, а var in deleg { sta_inl_func } = 2 ?
Чем отличается статическая компоновка inline функций от статической компоновки static inline функций?



ПРАВИЛЬНЫЙ ОТВЕТ: inline функции компонуются динамически если явно не указать обратное, т.е. static inline. Так же inline функции не подчиняются правилу ODR. Расхожее мнение что inline функции компонуются статически в корне неверно. Компилятор у VC 2005 - г о в н огадость.
----------------------------------------------
результат (сборка g++ 4.3.3 linux)
Код

var in deleg { dyn_func } = 2
var in deleg { sta_func } = 2
var in deleg { inl_func } = 2
var in deleg { sta_inl_func } = 2

var in main { dyn_func } = 2
var in main { sta_func } = 1
var in main { inl_func } = 2
var in main { sta_inl_func } = 1


Это сообщение отредактировал(а) Леопольд - 20.6.2009, 10:48


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
azesmcar
Дата 19.6.2009, 10:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата

When you declare a variable or function at file scope (global and/or namespace scope), the static keyword specifies that the variable or function has internal linkage. When you declare a variable, the variable has static duration and the compiler initializes it to 0 unless you specify another value.

это ответ на вопрос
Цитата

Чем отличается статическая компоновка inline функций от статической компоновки static inline функций? 

он же "частичный ответ". Думаю дальше додумать будет несложно.

Это сообщение отредактировал(а) azesmcar - 19.6.2009, 10:13
PM   Вверх
mes
Дата 19.6.2009, 10:16 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Леопольд @  19.6.2009,  08:56 Найти цитируемый пост)
static int var = 0;

из за ее  расположения в хидере, у Вас получаются две переменные (по одной в каждой единице трансляции)
тут разобрано подробнее :
http://www.rsdn.ru/forum/cpp/2706624.1.aspx


Это сообщение отредактировал(а) mes - 19.6.2009, 10:19


--------------------
PM MAIL WWW   Вверх
Леопольд
Дата 19.6.2009, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(mes @ 19.6.2009,  10:16)
Цитата(Леопольд @  19.6.2009,  08:56 Найти цитируемый пост)
static int var = 0;

из за ее  расположения в хидере, у Вас получаются две переменные (по одной в каждой единице трансляции)
тут разобрано подробнее :
http://www.rsdn.ru/forum/cpp/2706624.1.aspx

Да, я понимаю что у меня две переменные, этот пример сделан для наглядной демонстрации статической компоновки. Я не понимаю почему инлайн функция (без спецификатора static), вызываемая из другой единицы трансляции (при помощи делегирования) выводит значение переменной из той единицы трансляции где происходит вызов делегата а не из той, где делегат определён. Поправьте меня, если я не прав, и inline не подразумевает статическую компоновку.

Если что, вопрос в самом низу первого поста...

Добавлено @ 12:39
Цитата(azesmcar @ 19.6.2009,  10:10)
Цитата

When you declare a variable or function at file scope (global and/or namespace scope), the static keyword specifies that the variable or function has internal linkage. When you declare a variable, the variable has static duration and the compiler initializes it to 0 unless you specify another value.

это ответ на вопрос
Цитата

Чем отличается статическая компоновка inline функций от статической компоновки static inline функций? 

он же "частичный ответ". Думаю дальше додумать будет несложно.

Прав ли я буду если скажу что inline как и static имеет internal linkage? Если да, то почему тогда они оперируют с разными инстансами переменной var хотя их вызов происходит одинаково, через делегата dyn_func?

Этому я не "вижу" объяснения. Буду премного благодарен если кто-нибдь мне "разжуёт"

Это сообщение отредактировал(а) Леопольд - 19.6.2009, 12:42


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
azesmcar
Дата 19.6.2009, 13:48 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



static inline имеет internal linkage, inline - имеет external linkage. (добавлено для точности: тут речь идет о ваших функциях а не вообще)
Цитата(Стандарт)

static char* f(); // f() has internal linkage
...
void h();
inline void h(); // external linkage


Цитата(Стандарт)

An inline function shall be defined in every translation unit in which it is used and shall have exactly the
same definition in every case (3.2). [Note: a call to the inline function may be encountered before its definition
appears in the translation unit. ] If a function with external linkage is declared inline in one translation
unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required. An
inline function with external linkage shall have the same address in all translation units. A static
local variable in an extern inline function always refers to the same object. A string literal in an
extern inline function is the same object in different translation units.

теперь понятнее?

Добавлено @ 13:49
Цитата(Леопольд @  19.6.2009,  12:32 Найти цитируемый пост)
Прав ли я буду если скажу что inline как и static имеет internal linkage? 

нет, см. стандарт

Это сообщение отредактировал(а) azesmcar - 19.6.2009, 14:15
PM   Вверх
Леопольд
Дата 19.6.2009, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Теперь всё встало на свои места, спасибо! Не стоит доверять всему подряд: 
Для функций, объявленных как подставляемые (с ключевым словом inline), по умолчанию тоже применяется внутренняя компоновка.
(с)http://www.rsdn.ru/forum/cpp/2706624.1.aspx

Это сообщение отредактировал(а) Леопольд - 19.6.2009, 13:59


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
zim22
Дата 19.6.2009, 14:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



Цитата(Леопольд @  19.6.2009,  13:56 Найти цитируемый пост)
Теперь всё встало на свои места. Не стоит доверять всему подряд:

ну а что вы хотели, чтобы LaptevVV (преподаватель) знал наизусть весь стандарт? ну ошибся человек, бывает smile


--------------------
PM MAIL   Вверх
Леопольд
Дата 19.6.2009, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(zim22 @ 19.6.2009,  14:00)
Цитата(Леопольд @  19.6.2009,  13:56 Найти цитируемый пост)
Теперь всё встало на свои места. Не стоит доверять всему подряд:

ну а что вы хотели, чтобы LaptevVV (преподаватель) знал наизусть весь стандарт? ну ошибся человек, бывает smile

Он не одинок. Мнение расхожее и встречалось мне во многих местах. Основная причина в том что определённые в теле класса функции считаются inline по умолчанию. Дабы не нарушать ODR.

Так что не всё встало на свои места, увы. Теперь я не понимаю почему на inline не действует ODR? Ведь определение функции находится в хидере который включается в два модуля. Почему нет ошибки? Если попробовать перенести определение dyn_func в хидер то получим ошибку на этапе линковки...

Это сообщение отредактировал(а) Леопольд - 19.6.2009, 14:14


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
azesmcar
Дата 19.6.2009, 14:11 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Леопольд

Вообще-то ключевое слово inline никак не влияет на linkage функции. Просто в вашем случае inline обявлена функция с external linkage.
Речь идет о inl_func. В случае с sta_inl_func инлайнится функция с internal linkage.

Цитата(Леопольд @  19.6.2009,  14:10 Найти цитируемый пост)
Вру, не всё встало на свои места. Теперь я не понимаю почему на inline не действует ODR? 

так задуманно smile
Цитата

3.2 One Definition Rule:

5 There can be more than one definition of a class type (Clause 9), concept (14.9), concept map (14.9.2), enumeration type (7.2), inline function with external linkage (7.1.2), [...]

Цитата

An inline function shall be defined in every translation unit in which it is used and shall have exactly the
same definition in every case...




Это сообщение отредактировал(а) azesmcar - 19.6.2009, 14:29
PM   Вверх
Леопольд
Дата 19.6.2009, 14:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Я тоже пришёл к такому же выводу, правда только дедуктивно... Спасибо! Теперь даже сомнений не осталось. smile Вопрос закрыт.
И всё же, ответ был найден в стандарте а не в the книгах  smile 

Это сообщение отредактировал(а) Леопольд - 19.6.2009, 14:42


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
azesmcar
Дата 19.6.2009, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(Леопольд @  19.6.2009,  14:39 Найти цитируемый пост)
Я тоже пришёл к такому же выводу, правда только дедуктивно... Спасибо! Теперь даже сомнений не осталось. smile Вопрос закрыт.
И всё же, ответ был найден в стандарте а не в the книгах  smile 

Стандарт мне цитировать легче чем книги. Еще надо вспомнить где и что написано. А самому писать неохота smile так легче, и ответ и доказательство в одном лице.
PM   Вверх
zim22
Дата 19.6.2009, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



Цитата(Леопольд @  19.6.2009,  14:10 Найти цитируемый пост)
 Основная причина в том что определённые в теле класса функции считаются inline по умолчанию

inline - это рекомендация/просьба компилятору. а встроит он или нет - дело его.

Добавлено @ 15:10
Цитата(Леопольд @  19.6.2009,  14:10 Найти цитируемый пост)
Дабы не нарушать ODR.

что-то мне кажется, что в С++ это правило всё-равно нарушается.
ведь можно же объявлять struct\class\union\enum структуру и функцию с одинаковым именем в одной области видимости.
Код

struct S {};
int S();

***
azesmcar уже ответил на этоsmile

Это сообщение отредактировал(а) zim22 - 19.6.2009, 15:12


--------------------
PM MAIL   Вверх
Леопольд
Дата 19.6.2009, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(zim22 @ 19.6.2009,  15:05)
Цитата(Леопольд @  19.6.2009,  14:10 Найти цитируемый пост)
 Основная причина в том что определённые в теле класса функции считаются inline по умолчанию

inline - это рекомендация/просьба компилятору. а встроит он или нет - дело его.

Дело в том, что если бы это было не так, то нельзя было бы определять функции в теле класса. Было бы нарушено ODR. А так как extern inline функции не подвалстны ODR (при определённых условиях) то они идеальный кандидат на эту роль. А встроится эта функция, или нет, не имеет значения в этом контексте.


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
azesmcar
Дата 19.6.2009, 15:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата

A function defined within a class definition is an inline function. The inline specifier shall not appear
on a block scope function declaration.79)

...
Цитата

A function declaration (8.3.5, 9.3, 11.4) with an inline specifier declares an inline function. The inline
specifier indicates to the implementation that inline substitution of the function body at the point of call is
to be preferred to the usual function call mechanism. An implementation is not required to perform this
inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for
inline functions defined by 7.1.2 shall still be respected.



Добавлено через 2 минуты и 27 секунд
что я хотел сказать...
функция может и не встроится, а может встроится в одном участке кода и не встроится в другом..но от этого она не перестанет быть инлайн функцией. 
PM   Вверх
zim22
Дата 19.6.2009, 15:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



Цитата(azesmcar @  19.6.2009,  15:30 Найти цитируемый пост)
функция может и не встроится, а может встроится в одном участке кода и не встроится в другом

с чего вы это взяли?


--------------------
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1461 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.