Перейти к содержанию
    

Добавил к программе еще немного вывода текстовых строк, задал их в виде массива, условно:

const char *Text[] = { "text1", "text2", "text3" };

И функцию, естественно, для вывода, аналогичную другим таким же.

И - завалил программу! Улетает при старте в HardFault, как понял, из недр RTOS (Keil CMSIS-RTOS RTX), пытаясь выделить некую память из пула. Я и размер кучи изменял, и стек задач, и ничего не помогает.

Стал с прошлым вариантом сравнивать (вот где пришлись кстати TortoiseHg c Total Commander). Делаю небольшие изменения, компилирую, запускаю. Дошел до этого массива. И как только добавил static const char *Text.... все заработало.

Поможите люди добрые, объясните, как такое могёт быть? Проект выложить не могу, он великий и коммерческий. Хотелось бы понять принцип.

Файлов в проекте - штук 20. И память используется сильно, не могу сказать, вся / не вся. Если компилируется, значит, есть куда пихать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Массив - внутри функции. Имя - уникальное (реально - иное), проверил поиском по всем исходникам, удостоверился.

Глянул в map файл. Это имя нашлось в RAM. Как это? :w00t:

В массиве 40 строк, каждая по 6 символов, и плюс /0. Итого 280 байтов. Нигде в другом месте эти строки не повторяются, хотя, хвостики похожие можно найти. В map вижу размер 160 байтов, в RAM.

Не в том ли загадка, что задан массив статических указателей?

Получается, размер в ОЗУ точно равен размеру указателей!

Может, правильнее двумерный массив использовать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если это внутри функции, то, возможно, просто стека не хватает для не-static объявления. Каждый раз, при заходе в функцию, происходит выделение и массива указателей, и массива данных на стеке, и туда копируется содержимое. А в случае static - все статически лежит в .const (или .rodata). Вот и разница.

 

Правильно, использовать или static объявление, или вне ф-ции (и, тоже static). А вот объявлять такое внутри функции без static - категорически неправильно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если задаю const chat *Text, что заставляет компилятор не извлекать строки прямо из flash-памяти? Я же их только читаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если задаю const chat *Text, что заставляет компилятор не извлекать строки прямо из flash-памяти? Я же их только читаю.

Объявление переменной внутри ф-ции без "static" подразумевает, что переменная лежит на стеке, и всем совершенно все равно, только читаете Вы ее, или не только.

Так что, чтобы оно лежало во флеш - или объявляйте ВНЕ функции (тут static будет лишь ограничивать видимость идентификатора внутри файла, поэтому, он желателен, но не обязателен), или внутри функции, но обязательно со static.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Объявление переменной внутри ф-ции без "static" подразумевает, что переменная лежит на стеке, и всем совершенно все равно, только читаете Вы ее, или не только.

Так что, чтобы оно лежало во флеш - или объявляйте ВНЕ функции (тут static будет лишь ограничивать видимость идентификатора внутри файла, поэтому, он желателен, но не обязателен), или внутри функции, но обязательно со static.

 

Ну-ну...

тут тоже будет на переменная на стеке ?

 

int Foo(int arg)

{

const int A = 23;

 

return A+arg;

}

 

Умный компилятор сам должен разобраться в константах/переменных, а если он глючный и тупой, то придется глядеть в листинг.

Да, в случае с Ц++ статические объекты внутри функций ведут себя по-другому относительно чистого Ц.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

тут тоже будет на переменная на стеке ?

Если отключите все оптимизации, то должна быть именно там. Если включите, скорее всего этой переменной вообще не будет. Но не надо путать такой простой случай с массивом строк. Его в непосредственную константу не соптимизируешь. Разумеется, речь про С, без плюсов. С плюсами я не знаю, как оно обязано быть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Посмотрел листинги со static и без.

Для const при входе в функцию указатель стека опускается на 164, в R2 заносится 160, в R1 заносится адрес из области .constdata, затем SP копируется в R0 и вызывается __aeabi_memcpy4. В-общем, копируются указатели. Дальше идут манипуляции относительно указателя стека, а в конце он восстанавливается. В map-файле текстовый массив не упоминается.

Для static const указатель загружается из ОЗУ. В map-файле есть конкретное расположение массива указателей.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, о чем я и говорил. Скорее всего у Вас стека маловато, и он переполняется.

А чтобы расположить константы сразу во флеш, без копирования в ОЗУ, вероятно, надо с линкером помудрить, чтобы секция констант там оказалась (но флеш медленная, в отличие от ОЗУ, поэтому не факт, что всем константам там место). Кстати, в какой секции оказываются константы со static?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я сделал (?, проверю работоспособность завтра) иначе:

static const char * const Text[]

Теперь массив указателей размещен во flash.

Вижу, что размер RO-data увеличился на 160 байтов, а RW-data на столько же уменьшился.

:yeah:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Теперь массив указателей размещен во flash.

Только надо еще проверить, чтобы эта секция на самом деле во флеш попала, по мап-файлу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только надо еще проверить, чтобы эта секция на самом деле во флеш попала, по мап-файлу.

Да, я вижу адрес массива указателей в map-файле. И размер 160 байтов. Сами строки - где-то... ну, это как и должно быть.

Ох, наскребу завтра свободного ОЗУ!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я сделал (?, проверю работоспособность завтра) иначе:

static const char * const Text[]

Теперь массив указателей размещен во flash.

 

а чему удивляться-то ?

 

"const char*" это указатель на константу. содержимое по указателю изменять нельзя, а вот сам указатель - можно.

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

эти переменные никогда не меняются и сделать соотв. оптимизацию.

 

"const char* const" это константрый указатель на константу. ни его, ни значение по его адресу менять нельзя.

 

ИМХО, комбинировать в разных сочетаниях static & const в надежде, что компилятор запихнет что-то во флэш, это непрофессиональные танцы с бубном.

Завтра выйдет новая версия компилятора, или флаг оптимизации кто поменяет и все развалится.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

static const *text[] используется у отцов-основателей K&R, но не объясняется, зачем. Аналогично у Шилдта.

static const * const text описывается в руководстве на компилятор Hi-Tech для PIC.

Пользуюсь Keil, круче компилятора нет, imho.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...