|
static const vs const, ошарашен! |
|
|
|
Jan 14 2015, 16:02
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Добавил к программе еще немного вывода текстовых строк, задал их в виде массива, условно: const char *Text[] = { "text1", "text2", "text3" }; И функцию, естественно, для вывода, аналогичную другим таким же. И - завалил программу! Улетает при старте в HardFault, как понял, из недр RTOS (Keil CMSIS-RTOS RTX), пытаясь выделить некую память из пула. Я и размер кучи изменял, и стек задач, и ничего не помогает. Стал с прошлым вариантом сравнивать (вот где пришлись кстати TortoiseHg c Total Commander). Делаю небольшие изменения, компилирую, запускаю. Дошел до этого массива. И как только добавил static const char *Text.... все заработало. Поможите люди добрые, объясните, как такое могёт быть? Проект выложить не могу, он великий и коммерческий. Хотелось бы понять принцип. Файлов в проекте - штук 20. И память используется сильно, не могу сказать, вся / не вся. Если компилируется, значит, есть куда пихать?
|
|
|
|
|
Jan 14 2015, 16:19
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
а это сильно зависит от того, где определены эти строки (внутри ф-ции, или снаружи). В результате модификатора "static" может менятся секция, где размещены сами данные, а также может добавляться/убираться процес копирования этих данных в стек. Еще может быть, что в нескольких модулях определен символ с именем Text (и, при этом, вовсе не обязательно того же типа), и при объявлении без static (и вне ф-ции), объявление этого символа глобальным убивает что-то еще, совсем не тут.
|
|
|
|
|
Jan 14 2015, 16:23
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Массив - внутри функции. Имя - уникальное (реально - иное), проверил поиском по всем исходникам, удостоверился. Глянул в map файл. Это имя нашлось в RAM. Как это?  В массиве 40 строк, каждая по 6 символов, и плюс /0. Итого 280 байтов. Нигде в другом месте эти строки не повторяются, хотя, хвостики похожие можно найти. В map вижу размер 160 байтов, в RAM. Не в том ли загадка, что задан массив статических указателей? Получается, размер в ОЗУ точно равен размеру указателей! Может, правильнее двумерный массив использовать?
|
|
|
|
|
Jan 14 2015, 16:40
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Если это внутри функции, то, возможно, просто стека не хватает для не-static объявления. Каждый раз, при заходе в функцию, происходит выделение и массива указателей, и массива данных на стеке, и туда копируется содержимое. А в случае static - все статически лежит в .const (или .rodata). Вот и разница.
Правильно, использовать или static объявление, или вне ф-ции (и, тоже static). А вот объявлять такое внутри функции без static - категорически неправильно.
|
|
|
|
|
Jan 14 2015, 16:59
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(ViKo @ Jan 14 2015, 19:47)  Если задаю const chat *Text, что заставляет компилятор не извлекать строки прямо из flash-памяти? Я же их только читаю. Объявление переменной внутри ф-ции без "static" подразумевает, что переменная лежит на стеке, и всем совершенно все равно, только читаете Вы ее, или не только. Так что, чтобы оно лежало во флеш - или объявляйте ВНЕ функции (тут static будет лишь ограничивать видимость идентификатора внутри файла, поэтому, он желателен, но не обязателен), или внутри функции, но обязательно со static.
|
|
|
|
|
Jan 14 2015, 19:03
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(SM @ Jan 14 2015, 16:59)  Объявление переменной внутри ф-ции без "static" подразумевает, что переменная лежит на стеке, и всем совершенно все равно, только читаете Вы ее, или не только. Так что, чтобы оно лежало во флеш - или объявляйте ВНЕ функции (тут static будет лишь ограничивать видимость идентификатора внутри файла, поэтому, он желателен, но не обязателен), или внутри функции, но обязательно со static. Ну-ну... тут тоже будет на переменная на стеке ? int Foo(int arg) { const int A = 23; return A+arg; } Умный компилятор сам должен разобраться в константах/переменных, а если он глючный и тупой, то придется глядеть в листинг. Да, в случае с Ц++ статические объекты внутри функций ведут себя по-другому относительно чистого Ц.
|
|
|
|
|
Jan 14 2015, 20:06
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Ну, о чем я и говорил. Скорее всего у Вас стека маловато, и он переполняется. А чтобы расположить константы сразу во флеш, без копирования в ОЗУ, вероятно, надо с линкером помудрить, чтобы секция констант там оказалась (но флеш медленная, в отличие от ОЗУ, поэтому не факт, что всем константам там место). Кстати, в какой секции оказываются константы со static?
|
|
|
|
|
Jan 14 2015, 23:38
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(ViKo @ Jan 14 2015, 20:12)  Я сделал (?, проверю работоспособность завтра) иначе: Код static const char * const Text[] Теперь массив указателей размещен во flash. а чему удивляться-то ? "const char*" это указатель на константу. содержимое по указателю изменять нельзя, а вот сам указатель - можно. То есть его в теории нельзя пихать в RO - секцию. С другой стороны, умный компилятор мог бы и разобраться, что эти переменные никогда не меняются и сделать соотв. оптимизацию. "const char* const" это константрый указатель на константу. ни его, ни значение по его адресу менять нельзя. ИМХО, комбинировать в разных сочетаниях static & const в надежде, что компилятор запихнет что-то во флэш, это непрофессиональные танцы с бубном. Завтра выйдет новая версия компилятора, или флаг оптимизации кто поменяет и все развалится.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|