Easyelectronics.ru

Электроника для всех
Текущее время: 13 дек 2018, 02:19

Часовой пояс: UTC + 5 часов




Начать новую тему Ответить на тему  [ Сообщений: 13 ] 
Автор Сообщение
 Заголовок сообщения: помогите разобраться с сишным inline
СообщениеДобавлено: 30 янв 2018, 20:04 
Только пришел

Зарегистрирован: 06 окт 2015, 15:47
Сообщения: 27
а то себя ощущаю стоящим на лыжах...

Код:
int timer_waitx( uint16_t d , volatile uint8_t *f)
{
   *f = true;
   return scheduler_timer_add_flag( d , f );
}
inline void waitx( uint16_t d , volatile uint8_t *f)
{
   if( !timer_waitx( d , f ) ) hangup_device( ERROR_SCHEDULER );
}


В этом же файле
Код:
      waitx( 500 , &wait_delay_flag );


И при компиляции (вернее уже при линковке) ошибки:
/home/slav/src/t.c:292: undefined reference to `waitx'

Компилятор arm-none-eabi-gcc (Fedora 7.1.0-2.fc26) 7.1.0 , целевой процессор stm32f0

Чего ему надо?

что компилятор, судя по ассемблерному коду, решил что оптимально все-таки вызывать функцией, а не вставлять этот код напрямую, оставим на его совести, следующей ключу -Os.
Но куда он тогда саму функцию-то дел? Я могу выкинуть inline, что бы все скомпилировалось, но хотелось бы понять причину.
Причем ему не нравится именно эта функция и еще одна такая же, в которой после вызова timer_waitx крутится while(!*f); Остальные функции с inline'ом он нормально переваривает: какие-то вставляет напрямую в код, какие-то оформляет все-таки отдельным вызовом. А что ему в этой не нравится, я второй день понять не могу.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 30 янв 2018, 20:23 
Старожил

Зарегистрирован: 07 авг 2014, 17:15
Сообщения: 383
Откуда: дальнее надмосковье
А где объявление функции в заголовочном файле? Или все происходит в одном файле? Тогда где static? А если в разных файлах то попробуйте объявить extern inline в одном *.с файле а в заголовочном файле прописать функцию как inline (последняя ссылка). Ну и не забыть поставить стандарт хотя бы C99 или больше.

https://stackoverflow.com/questions/631 ... ful-in-c99
https://stackoverflow.com/questions/631 ... 13#6312813
https://gustedt.wordpress.com/2010/11/2 ... ne-in-c99/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 30 янв 2018, 20:32 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 1622
Откуда: Китай, Пекин
kettle писал(а):


В этом же файле
Код:
      waitx( 500 , &wait_delay_flag );


И при компиляции (вернее уже при линковке) ошибки:
/home/slav/src/t.c:292: undefined reference to `waitx'


В этом же файле файле - выше или ниже. это важно!
да, сишные компиляторы не прилично туповаты по современным стандартам.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 30 янв 2018, 21:18 
Только пришел

Зарегистрирован: 06 окт 2015, 15:47
Сообщения: 27
arm999 писал(а):
А где объявление функции в заголовочном файле? Или все происходит в одном файле? Тогда где static?



Все в одном файле. Но да, я дебил и забыл про static, поскольку привык, что static указывает что не надо экспортировать соответствующий символ, а тело функции здесь же и определено.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 30 янв 2018, 21:27 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 3156
Откуда: КЧР, поселок Нижний Архыз
gcc без указания true inline запросто может функцию и не инлайнить, если посчитает это более оптимальным!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 31 янв 2018, 00:46 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2536
Откуда: Санкт-Петербург
Не только gcc: так и по стандарту можно. Лет 10-15 назад натыкался на такое поведение у MSVC, там ситуация усугублялась тем, что если функция не инлайнилась - то на каждое включение хедера с ней создавалось по экземпляру функции, и я получал duplicate symbol definition, пока не сделал её __force_inline. (на самом деле сам виноват - надо было писать хотя бы static inline, но в нынешних версиях компиляторов это необязательно)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 31 янв 2018, 02:44 
Старожил

Зарегистрирован: 17 дек 2014, 04:38
Сообщения: 518
Доброго времени суток !

Во первых - inline это рекомендация, а не опция. Во вторых - inline функция может быть ТОЛЬКО в одном и том же файле, в противном случае она проходит, но уже как обычная функция. Это обусловлено тем, что компилятор при компиляции может куда-то вставлять или не вставлять код. Редактор связей (линковщик) с кодом не работает, он работает с таблицей имен. К стати, когда вы используете ключевое слово static, данное имя (функции или переменной) в таблицу имен не заносится. В начало .c файла внесите
Код:
static inline void waitx( uint16_t d , volatile uint8_t *f);
И все увидится. Не буду утверждать наверняка, но я думаю что если ваша переменная wait_delay_flag глобальна, то компилятор будет игнорировать inline.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 31 янв 2018, 02:50 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 3156
Откуда: КЧР, поселок Нижний Архыз
Как раз инлайновым функциям место в заголовочных файлах! И по-человечески "библиотеки" для МК надо именно так делать: на макросах и чистых инлайнах. А не как всякие ушлепки делают (что абдуринщики, что STM в своем сначала SPL, а потом калокубе).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 31 янв 2018, 03:27 
Только пришел

Зарегистрирован: 06 окт 2015, 15:47
Сообщения: 27
aamonster писал(а):
то на каждое включение хедера с ней создавалось по экземпляру функции,

У меня обратная ситуация: ни одного экземпляра. :)

void1509 писал(а):
Доброго времени суток !

Во первых - inline это рекомендация, а не опция. Во вторых - inline функция может быть ТОЛЬКО в одном и том же файле, в противном случае она проходит, но уже как обычная функция. ... Не буду утверждать наверняка, но я думаю что если ваша переменная wait_delay_flag глобальна, то компилятор будет игнорировать inline.

Она и есть в одном и том же файле. Там весь "проект" один Сишный файл, где эта функция и определяется и вызывается.
Дело не том, что функция не инлайнится, а в том, что она вообще пропадает. Просто я не ожидал что компилятор без указания static не будет ее компилировать в этом модуле, а оставит линковщику искать где-то еще.

Получается код:
Код:
      movs   r0, #250
   movs   r5, r4
   adds   r5, r5, #88
   movs   r1, r5
   lsls   r0, r0, #1
   bl   waitx

А метки waitx нет. Т.е. код этой функции отсутствует. Ну, видимо, компилятор считает что он в каком-то другом файле уже будет.

И компилятору не все ли равно глобальная или локальная там переменная? Ему же нужен только ее адрес?
Если я правильно понимаю, то в коде выше в r1 как раз ее адрес и заносится. И дальше, как мне кажется, совершенно не важно, что вызывать: waitx, или ее заинлайнить и вызвать timer_waitx с тем же набором и порядком передаваемых переменных.

Eddy_Em писал(а):
Как раз инлайновым функциям место в заголовочных файлах! И по-человечески "библиотеки" для МК надо именно так делать: на макросах и чистых инлайнах. А не как всякие ушлепки делают (что абдуринщики, что STM в своем сначала SPL, а потом калокубе).

Я кубик использую только что бы посмотреть на какие ноги какую перефирию можно назначить, что бы упростить разводку платы. А остальное из opencm3 беру, но там тоже не оптимально, кмк, типа такого:

Код:
void gpio_set(uint32_t gpioport, uint16_t gpios)
{
   GPIO_BSRR(gpioport) = gpios;
}


Для одной команды МК установки значения порта добавляется еще два перехода: на подпрограмму и обратно. Кмк такие функции должны быть именно макросами, ну или инлайнами, если хочется типы проверить. Толи я чего-то не понимаю, толи это реально лажа.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 31 янв 2018, 10:17 
Старожил

Зарегистрирован: 26 ноя 2012, 10:28
Сообщения: 3156
Откуда: КЧР, поселок Нижний Архыз
Я от opencm3 отказался: слишком часто они стали API ломать! Нафиг этот график!!!
Особенно, учитывая то, как они часто используемую элементарщину реализовали: ведь действительно, эти кони функции вызывают вместо того, чтобы оформить макросом или на крайняк true inline.
Цитата:
толи это реально лажа

Скорее всего, именно это. Очень напоминает абдуриноподход: там тоже срать хотели на производительность - лишь бы юзверю можно было в три клацания мышей светодиодиком помыргать.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 31 янв 2018, 13:49 
Только пришел

Зарегистрирован: 06 окт 2015, 15:47
Сообщения: 27
Eddy_Em писал(а):
Скорее всего, именно это. Очень напоминает абдуриноподход: там тоже срать хотели на производительность - лишь бы юзверю можно было в три клацания мышей светодиодиком помыргать.


кмк у ардуинщиков подход чуть другой: там, например, digitalWrite не просто бит устанавливает или сбрасывает. А opencm в функции именно одно действие: записать значение в регистр.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 31 янв 2018, 14:42 
Заглядывает иногда

Зарегистрирован: 15 ноя 2015, 12:11
Сообщения: 130
Гипотеза: функция вызвана до того, как объявлена. Компилятор при первом использовании считает её возвращающей int, затем находит нечто одноименное но void, которое выбрасывает, потому как "ведь всё равно инлайн и нигде не используемо-же". В итоге у линкера язык за спину заворачивается в поисках того чего нету.
А если [по приколу] в проблемном файле тип waitx сменить void -> int изменится поведение? Ну а потом прототип void waitx() заблаговременно прописать до вызова если ещё не.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: помогите разобраться с сишным inline
СообщениеДобавлено: 31 янв 2018, 16:28 
Только пришел

Зарегистрирован: 06 окт 2015, 15:47
Сообщения: 27
siarzhuk писал(а):
Гипотеза: функция вызвана до того, как объявлена.


Гипотеза неправильная, во-первых объявление до вызова, а во-вторых вызов без объявления порождает варнинг еще при компиляции: implicit declaration of function
В данном случае имеет место быть особенности поведения при inline, static inline и extern inline.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 13 ] 

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB