Mikhail1954 0 26 октября, 2009 Опубликовано 26 октября, 2009 · Жалоба Всем доброго времени суток! Просветите, пожалуйста. Есть такая функция, которая чинно-благородно вызывает другую функцию, а та еще одну, а та еще одну - и рисует буковку. void RenderStringDisplay(const char *pString, const CharInfo *pFont, uint16 row, uint16 column, uint16 spacing, uint16 address) { uint16 x, y, initColumn; const CharInfo *pCharInfo; initColumn = column; // Loop through characters until NULL (0) found. while (*pString) { if (*pString == '\n') // Newline character? { column = initColumn; row += spacing; } else // Not new line. { // Compute pointer to font information for current character. pCharInfo = &pFont[(unsigned char)*pString]; // Compute origin of character bounding box. x = column + pCharInfo->offsetX; y = row - pCharInfo->offsetY - pCharInfo->height + 1; // Display the character DrawDisplayCharacter(pCharInfo, y, x, address); // Advance along line by appropriate horizontal spacing. column += pCharInfo->dwidth; } // Advance to next character. pString++; } } Все это прекрасно работает в отладчике, однако при возврате указатель стека уменьшается на 4. После нескольких вызовов уже начинает ругаться отладчик на переполнение стека. Впрочем, программа никуда не улетает и продолжает работать. Все прерывания запрещены. Если выбрать опцию reduce stack usage, то это дело прекращается, SP при возврате возвращается точно назад. Что бы это значило? При этом более простенькии функции с меньшей иерархией вложений стек отдают. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VAI 0 26 октября, 2009 Опубликовано 26 октября, 2009 · Жалоба Непрятно разбираться в тексте, когда Вы игнорируете форматирование. Вы не первый раз пишете, не новичок, "свой", разве трудно выделить код и нажать на иконку "Код" (самая левая). Это же неуважение к тем, кого Вы спрашиваете... Вы можете включить генерацию ассемблерного листинга и найти, где Вас компилятор обманывает. Конкретно по Вашему компилятору ничего не скажу, я использую старую версию 3.30, а вложений у меня очень много и прерывания разрешены, стек не утекает... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Mikhail1954 0 26 октября, 2009 Опубликовано 26 октября, 2009 · Жалоба Обманывает, конечно. Вот кусок call frame, каждый повторный вызов RenderStringDisplay смещает стек на 4, пока дело не дойдет до "приличных" функций, которые стек не отгрызают. FUNCALL main, RenderStringDisplay LOCFRAME CSTACK, 12, STACK FUNCALL main, RenderStringDisplay LOCFRAME CSTACK, 16, STACK FUNCALL main, RenderStringDisplay LOCFRAME CSTACK, 20, STACK ............................................. FUNCALL main, RenderStringDisplay LOCFRAME CSTACK, 32, STACK FUNCALL main, RenderCursor LOCFRAME CSTACK, 32, STACK FUNCALL main, WaitNonBusy LOCFRAME CSTACK, 32, STACK Удивительно, но через какое-то время стек "вдруг" отдается. FUNCALL main, EnableRXInterrupts LOCFRAME CSTACK, 32, STACK FUNCALL main, RenderCursor LOCFRAME CSTACK, 8, STACK Т.е. как бы все само излечивается. Однако факт переполнения стека отладчиком отмечается, что не есть хорошо. Вот такая странность. Ну и если reduce stack usage, что, вроде, ухудшает код, то этих фокусов не наблюдается. FUNCALL main, ClearDisplayImageBuffer LOCFRAME CSTACK, 8, STACK FUNCALL main, RenderStringDisplay LOCFRAME CSTACK, 12, STACK FUNCALL main, RenderStringDisplay LOCFRAME CSTACK, 12, STACK .................................................... FUNCALL main, RenderStringDisplay LOCFRAME CSTACK, 12, STACK FUNCALL main, RenderCursor LOCFRAME CSTACK, 8, STACK Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VAI 0 27 октября, 2009 Опубликовано 27 октября, 2009 · Жалоба Кстати, если в опциях проекта (я пишу для v3.30, в Ваше может быть несколько по иному, но смысл понятен), в категрии "Linker" во вкладке "Cmd Opt" поставить птичку "Use command line options" и вписать там -xmos, то в конце map-файла будет CALL GRAPH - там использование стека Вашей программой. Основываясь на этих данных Вы увеличиваете стек в категории "General Options" во вкладке "Stack/Heap". Кстати, генерацию ассемблерного листинга включать в категории "C/C++ compiler" во вкладке "List" - птички "Ounput list file" и под ней "Assembler mnemonics" - позновательно иногда смотреть, что компилятор городит... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться