Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите разобраться с динамическим выделением памяти
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Alexey75
Пишу программу для LPC2214 с внешней SRAM, разместил область стека во внуреннем ОЗУ, а кучу во внешнем, но при использовании функций динамического выделения памяти прога зависает. Как оказалось проблема в том что куча находится выше указателя стека и из-за этого выдается ошибка ENOMEM. После поисков в internet и в документации к Newlib, стало ясно что надо написать другой вариант фунции sbrk, но при этом возникли вопросы:
1. как называть новую переопределяемую функцию (в разных местах ее называют как sbrk, _sbrk, _sbrk_r, может еще как-нибудь)
2. как пристроить эту новую функцию, чтобы она заменила существующую библиотечную и линкер бы не ругался
zltigo
Цитата(Alexey75 @ Dec 21 2006, 12:45) *
Как оказалось проблема в том что куча находится выше указателя стека и из-за этого выдается ошибка ENOMEM.

Абсолютно все равно где находится стек. Что-то у Вас с причиной другое совсем.
И какое отношение sbrk() к описанной проблеме при попытке динамического выделения памяти вообще имеет. А как Вы вообще представляете реаллокацию памяти на контроллерах класса ARM7?
Alexey75
Цитата(zltigo @ Dec 21 2006, 13:53) *
Цитата(Alexey75 @ Dec 21 2006, 12:45) *

Как оказалось проблема в том что куча находится выше указателя стека и из-за этого выдается ошибка ENOMEM.

Абсолютно все равно где находится стек. Что-то у Вас с причиной другое совсем.


Я делал пошаговое выполнение, так вот в функции _sbrk проверяется, чтобы выделяемая область памяти не попадала на стек:

caddr_t
_sbrk (int incr)
{
extern char end asm ("end"); /* Defined by the linker. */
static char * heap_end;
char * prev_heap_end;

if (heap_end == NULL)
heap_end = & end;

prev_heap_end = heap_end;

if (heap_end + incr > stack_ptr)
{
/* Some of the libstdc++-v3 tests rely upon detecting
out of memory errors, so do not abort here. */
#if 0
extern void abort (void);

_write (1, "_sbrk: Heap and stack collision\n", 32);

abort ();
#else
errno = ENOMEM;
return (caddr_t) -1;
#endif
}

heap_end += incr;

return (caddr_t) prev_heap_end;
}
zltigo
Цитата(Alexey75 @ Dec 21 2006, 13:28) *
Я делал пошаговое выполнение, так вот в функции _sbrk

Для начала Вы написали следующее:
Цитата
при использовании функций динамического выделения памяти прога зависает.

Между написанным и неработоспособностью некой _sbrk() - изменяющей размер хипа и не имеющей, отношения к привычному системному вызову sbrk() есть разница.

А есть-ли вообще необходимость на ходу менять размер heap? Что там за границей у Вас находится?
"Ничего"? Так отдайте сразу все под heap.
Цитата
2. как пристроить эту новую функцию, чтобы она заменила существующую библиотечную и линкер бы не ругался

Ну а если желаете создать иллюзию изменения - то просто напишите свою выкинув контроль и она будет молча использоваться вместо библиотечной.
Alexey75
Я видимо не совсем ясно выразился, когда задавал вопрос. Вобщем то у меня нет желания делать какие-то навороты по управлению памятью. Проблема возникает когда я размещаю стек во внутренней памяти LPC2214, а heap во внешней (большего размера). Если разместить heap ниже стека то все работает нормально, уже проверил. Просто хотелось бы чтобы стек находился в быстрой внутренней памяти, но там мало места, чтобы размещать там и heap.

По большому счету я понял что делать, у меня просто не получилось сделать так, чтобы при компиляции вместо библиотечной функции использовалась измененная мной функция.
zltigo
Цитата(Alexey75 @ Dec 21 2006, 14:30) *
Вобщем то у меня нет желания делать какие-то навороты по управлению памятью. Проблема возникает когда я размещаю стек во внутренней памяти LPC2214, а heap во внешней (большего размера). Если разместить heap ниже стека то все работает нормально, уже проверил. Просто хотелось бы чтобы стек находился в быстрой внутренней памяти, но там мало места, чтобы размещать там и heap.

Все пожелания абсолютно логичны. Проблема не понятна, ибо _sbrk() это уже перераспледеление размера heap. Или они ее и для инициализации размера (я не в курсе) heap используют? В общем если так, то просто выкиньте "контроль" и поместите результат в свой проект.
Цитата
По большому счету я понял что делать, у меня просто не получилось сделать так, чтобы при компиляции вместо библиотечной функции использовалась измененная мной функция.

Даже затрудняюсь предположить, что можно сделать "не так" sad.gif
Alexey75
Цитата(zltigo @ Dec 21 2006, 15:40) *
Цитата

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

Даже затрудняюсь предположить, что можно сделать "не так" sad.gif


Не хотелось бы задавать глупые вопросы, но как сделать, чтобы компилятор не обращал внимание на существование библиотечной функции, а брал бы новый вариант функции.
zltigo
Цитата(Alexey75 @ Dec 21 2006, 15:01) *
но как сделать, чтобы компилятор не обращал внимание на существование библиотечной функции, а брал бы новый вариант функции.

Третий раз пишу - написать свою одноименную и все. Не представляю, по каким причинам сие может не
сработать.
Alexey75
Цитата(zltigo @ Dec 21 2006, 16:06) *
Цитата(Alexey75 @ Dec 21 2006, 15:01) *

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

Третий раз пишу - написать свою одноименную и все. Не представляю, по каким причинам сие может не
сработать.

С третьего раза я понял о чем вы говорите smile.gif , буду разбираться с компилятором
Сергей Борщ
Цитата(Alexey75 @ Dec 21 2006, 15:10) *
С третьего раза я понял о чем вы говорите smile.gif , буду разбираться с компилятором
Если файл в котором будете определять функцию компилится в режиме C++, то надо функцию объявить с extern "C", иначе она получит другое "С++ное" внутреннее имя и, соответственно, не заменит библиотечную.
zltigo
Цитата(Сергей Борщ @ Dec 21 2006, 16:38) *
Если файл в котором будете определять функцию компилится в режиме C++, то надо функцию объявить с extern "C", иначе она получит другое "С++ное" внутреннее имя и, соответственно, не заменит библиотечную.

А что производители компиляторов уже начали писать библиотечные хидеры без extern "С" smile.gif?
Хотя конечно если не включить готовый хидер и наплевать на вопли об отсутствии прототипа, то добиться вышеописанного можно sad.gif
SergeyDDD
Когда идет инициализация стеков и кучи, внешняя память не подключена к процессору.
На сколько я помню, кроме контроллера внешней памяти еще необходимо соответственно настраивать совмещенные с шиной памяти порты.
Может в этом проблема
Alexey75
Проблема решилась, когда я подменил не функцию _sbrk, а функцию _sbrk_r, файл _sbrk_r.c был взят из newlib-lpc_rel_5a. В результате линкер перестал ругаться, что встретил два определения функции и нормально подменил библиотечную функцию.
Сергей Борщ
Цитата(zltigo @ Dec 21 2006, 17:00) *
А что производители компиляторов уже начали писать библиотечные хидеры без extern "С" smile.gif?
Хотя конечно если не включить готовый хидер и наплевать на вопли об отсутствии прототипа, то добиться вышеописанного можно sad.gif
В некоторых случаях совсем необязательно включать хидер, ибо определение функции является и объявлением. Например я постоянно использую свое определение extern "C" __low_level_init(), но при этом никакой дополнительный хидер в main.cpp не включаю.
zltigo
Цитата(Сергей Борщ @ Dec 22 2006, 16:20) *
Например я постоянно использую свое определение extern "C" __low_level_init(), но при этом никакой дополнительный хидер в main.cpp не включаю.

__low_level_init() не есть библиотечная функция а просто IARовский прибамбас, посему вполне логично
для него отсутствует прототип в библиотечных хидерах и IAR выдает просто болванку в которой все в одном флаконе с хидером. Описывать-же "свои" прототипы для стандартных библиотечных функций есть безобразие.
Сергей Борщ
Цитата(zltigo @ Dec 22 2006, 17:55) *
Цитата(Сергей Борщ @ Dec 22 2006, 16:20) *

Например я постоянно использую свое определение extern "C" __low_level_init(), но при этом никакой дополнительный хидер в main.cpp не включаю.

__low_level_init() не есть библиотечная функция а просто IARовский прибамбас, посему вполне логично
для него отсутствует прототип в библиотечных хидерах и IAR выдает просто болванку в которой все в одном флаконе с хидером. Описывать-же "свои" прототипы для стандартных библиотечных функций есть безобразие.
Прототипы = объявления, да. Но речь шла об определении = теле функции. Если по имени, параметрам и типу возвращаемого значения функция совпадает с библиотечной, то не вижу причины перед ее определением включать хидер с объявлением. Например в таком предельном случае когда под определение этой функции выделен отдельный исходный файл.
zltigo
Цитата(Сергей Борщ @ Dec 22 2006, 19:43) *
Если по имени, параметрам и типу возвращаемого значения функция совпадает с библиотечной, то не вижу причины перед ее определением включать хидер с объявлением.

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

абсолютно правилен и допустим и конкретно применен IARом для уже поминаемого ранее
__low_level_init() только вот к библиотекам не имеющим по определению файла с исходным текстом ну никакого отношения не имеет. Для библиотек отсутствие отдельного файла хидера невозможно.
Сергей Борщ
Цитата(zltigo @ Dec 22 2006, 19:59) *
Цитата(Сергей Борщ @ Dec 22 2006, 19:43) *

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

Вот для того, дабы абсолютно гарантированно выполнялось "параметрам и типу возвращаемого значения функция совпадает с библиотечной" и следует включать штатные библиотечные хидеры.
Тут трудно не согласиться, хотя для С++ функии отличающиеся типом и/или количеством параметров суть есть разные функции. Так что 100% гарантии давать не должно. Правда не знаю, относится ли это к функциям с квалификатором extern "C"
zltigo
Цитата(Сергей Борщ @ Dec 22 2006, 22:52) *
для С++ функии отличающиеся типом и/или количеством параметров суть есть разные функции.

Да в плюсах имя функции уродуется по полной программе и отражает, и параметры, и возвращаемое значение. Пару раз приходилось С++ функцию вызывать из ASM - разборки по полной программе sad.gif
Цитата
Так что 100% гарантии давать не должно.

??? Точнее, надо полагать не нуждается в прототипе для 100% гарантии.
Цитата
Правда не знаю, относится ли это к функциям с квалификатором extern "C"

Не относится, к счастью smile.gif - обычное добавление подчеркивания. Зато и без прототипа работать моветон sad.gif. И при ошибке в прототипе проблемы по полной программе. Библиотечные функции естественно в "C" а не "C++" стиле со всеми вытекающими удобствами и последствиями.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.