-
- Если _formatted_write принимает s приведённое к void*, то внутри функции просматриватся говнокод -- арифметика на void* указателями вообще не очень-то допустима... - fk0(22.01.2013 13:55)
- Почему? "современные стандарты требуют, чтобы представление и требования по выравниванию для void-указателей были теми же, что для указателей на char, что означает взаимозаменяемость этих типов." - Codavr(22.01.2013 14:40, ссылка)
- Нет... sizeof(*(void*)) у конкретного компилятора может быть неизвестно какой, а sizeof(*(char*)) == 1 всегда. У GCC исключение "расширение C", что sizeof в таком случае тоже == 1. Но для других компиляторов не так и бывает, что арифметика над fk0(364 знак., 22.01.2013 17:30)
- sizeof над такими выражениями у конкретного компилятора обязано выдавать ошибку. Codavr(226 знак., 23.01.2013 03:36 - 03:46, ссылка)
- Ошибка должна бы появиться еще раньше - на стадии разыменовывания указателя (void*). Или это не так? - Ксения(23.01.2013 03:40)
- Скорее всего. По крайней мере я такое рисовать точно не стал бы воизбежание недоразумений. По русски это звучит "Хрен знает что по адресу..." - Codavr(23.01.2013 03:48 - 04:07)
- Стихи: "Станем мы всю ночь гуглить, // Чтобы байтик занулить. // Головой об стену биться, // А не лучше ль нам смириться?" :) - Ксения(23.01.2013 03:55)
- :) - Codavr(23.01.2013 03:58)
- Смириться теперь, пожалуй, не получится - перед "молодым коллегой" несмываемый позор :) - Ксения(23.01.2013 04:01)
- :) - Codavr(23.01.2013 03:58)
- Стихи: "Станем мы всю ночь гуглить, // Чтобы байтик занулить. // Головой об стену биться, // А не лучше ль нам смириться?" :) - Ксения(23.01.2013 03:55)
- Скорее всего. По крайней мере я такое рисовать точно не стал бы воизбежание недоразумений. По русски это звучит "Хрен знает что по адресу..." - Codavr(23.01.2013 03:48 - 04:07)
- Ошибка должна бы появиться еще раньше - на стадии разыменовывания указателя (void*). Или это не так? - Ксения(23.01.2013 03:40)
- Стандарт говорит, что sizeof(void) вычислять не положено. А для арифметики (void*) следует приводить к (char*), ессно: стандарт гарантирует, что в этом случае всё будет вменяемо. Если получилось невменяемо, то такой компилятор/проц следует SciFi(34 знак., 22.01.2013 19:05)
- Ссылку на раздел C99, где говорится, что арифметика над void* нормальна? Вот тут утверждают обратное. - fk0(22.01.2013 19:33, ссылка)
- §6.2.6.1 пункт 27 Codavr(1934 знак., 23.01.2013 02:33 - 03:25, ссылка)
- Про арифметику здесь же не сказано. Что должно быть если два void* вычесть? Откуда компилятору знать sizeof в данном случае? - fk0(23.01.2013 11:56)
- Не надо ему знать это. Сейчас некогда рыть стандарт, но там есть пункт, где прописано, что любой указатель обязан быть даблом. Соответственно все правила для арифметики указателей, те же самые что для даблов. - Codavr(23.01.2013 12:02 - 12:08)
- Надоел уже. Нельзя делать арифметику с указателями на void: SciFi(288 знак., 23.01.2013 12:06)
- Этих слов я и ждал. А если в функцию передаётся void* то внутри неё по ошибке арифметику могли сделать. Я вот о чём. - fk0(23.01.2013 12:12)
- ... и получить на выходе компилера трехэтажный мат-перемат. - Codavr(23.01.2013 12:18)
- Неа! В лучшем случае warning, а то и вовсе ничего. Я ж говорю, нарывался (особенно GCC хорош, он в таком случае (void*) как (char*) воспринимает и "маскирует" ошибки), когда в таком случае результат неадекватный. С тех пор ка всю жизнь запомнил. fk0(45 знак., 23.01.2013 14:31)
- И что он в варнинге говорит? "есть опасность неправильно узнать расстояние между двумя объектами расположеными в разных разделах памяти, один в EEPROM, другой в ОЗУ, выберите предпочтительные единицы измерения (дюймы, миллиметры)" - Codavr(23.01.2013 15:31 - 15:34)
- Оба в EEPROM или оба в ОЗУ. Не важно. Важно, что void *p, *q; size_t x=p-q -- здесь в x расстояние в условных sizeof(void), которое может не быть == sizeof(char) как у GCC. - fk0(23.01.2013 17:10)
- Ну не юли. Если одно там, а другое там? - Codavr(23.01.2013 17:18)
- Если одно там, а другое там, то очевидно, полнейший глюкодром. Намекаешь, что оба приводятся к void? А вот фиг, у hitech, например const void* и void* две разные вещи могут быть (24 бита адрес если). И (const void*)0 != NULL вообще из-за 20-го fk0(8 знак., 23.01.2013 17:35)
- Я намекаю, что такое компилер не может как варнинг обрабатывать, если это компилер, а не глюкодром. Это конкрентный еррор. Ну или "вовсе ничего" ушел в себя и не вернулся :) - Codavr(23.01.2013 19:26 - 19:35)
- Кстати, про NULL вспомнилась забавная история: SciFi(300 знак., 23.01.2013 17:58)
- Если одно там, а другое там, то очевидно, полнейший глюкодром. Намекаешь, что оба приводятся к void? А вот фиг, у hitech, например const void* и void* две разные вещи могут быть (24 бита адрес если). И (const void*)0 != NULL вообще из-за 20-го fk0(8 знак., 23.01.2013 17:35)
- Ну не юли. Если одно там, а другое там? - Codavr(23.01.2013 17:18)
- Оба в EEPROM или оба в ОЗУ. Не важно. Важно, что void *p, *q; size_t x=p-q -- здесь в x расстояние в условных sizeof(void), которое может не быть == sizeof(char) как у GCC. - fk0(23.01.2013 17:10)
- Видимо, нельзя полагаться на сообщения компилятора в деле защиты от говнокода. Кстати, есть линты всякие и прочие static code analysis tools. - SciFi(23.01.2013 14:46)
- И что он в варнинге говорит? "есть опасность неправильно узнать расстояние между двумя объектами расположеными в разных разделах памяти, один в EEPROM, другой в ОЗУ, выберите предпочтительные единицы измерения (дюймы, миллиметры)" - Codavr(23.01.2013 15:31 - 15:34)
- Неа! В лучшем случае warning, а то и вовсе ничего. Я ж говорю, нарывался (особенно GCC хорош, он в таком случае (void*) как (char*) воспринимает и "маскирует" ошибки), когда в таком случае результат неадекватный. С тех пор ка всю жизнь запомнил. fk0(45 знак., 23.01.2013 14:31)
- ... и получить на выходе компилера трехэтажный мат-перемат. - Codavr(23.01.2013 12:18)
- И то верно. - Codavr(23.01.2013 12:10)
- Этих слов я и ждал. А если в функцию передаётся void* то внутри неё по ошибке арифметику могли сделать. Я вот о чём. - fk0(23.01.2013 12:12)
- Про арифметику здесь же не сказано. Что должно быть если два void* вычесть? Откуда компилятору знать sizeof в данном случае? - fk0(23.01.2013 11:56)
- Лехко: SciFi(502 знак., 22.01.2013 19:49)
- Это предположение. Мы не знаем, что там арифметика не делается с void. - fk0(22.01.2013 20:34)
- Вообще-то знаем: void - это такой тип, с которым никакая арифметика не делается. Хватит курить траву :-) - SciFi(22.01.2013 22:11)
- Я имею ввиду void* - fk0(22.01.2013 23:02)
- Вообще-то знаем: void - это такой тип, с которым никакая арифметика не делается. Хватит курить траву :-) - SciFi(22.01.2013 22:11)
- Это предположение. Мы не знаем, что там арифметика не делается с void. - fk0(22.01.2013 20:34)
- §6.2.6.1 пункт 27 Codavr(1934 знак., 23.01.2013 02:33 - 03:25, ссылка)
- Ссылку на раздел C99, где говорится, что арифметика над void* нормальна? Вот тут утверждают обратное. - fk0(22.01.2013 19:33, ссылка)
- sizeof над такими выражениями у конкретного компилятора обязано выдавать ошибку. Codavr(226 знак., 23.01.2013 03:36 - 03:46, ссылка)
- Нет... sizeof(*(void*)) у конкретного компилятора может быть неизвестно какой, а sizeof(*(char*)) == 1 всегда. У GCC исключение "расширение C", что sizeof в таком случае тоже == 1. Но для других компиляторов не так и бывает, что арифметика над fk0(364 знак., 22.01.2013 17:30)
- Почему? "современные стандарты требуют, чтобы представление и требования по выравниванию для void-указателей были теми же, что для указателей на char, что означает взаимозаменяемость этих типов." - Codavr(22.01.2013 14:40, ссылка)
- Это sprintf из IAR??? Ну здесь s может иметь неправильное значение. Интересуют подробности _formatted_write(). Можно написать s+=nr_of_chars (для оригинального значения) для проверки. Кроме того... Нет ли такой ситуации, что libc и проект fk0(98 знак., 22.01.2013 13:52)
- Выдернули исходный код из библиотеки и вставили в проект - ничего не меняется. - Vladimir Ljaschko(22.01.2013 15:12)
- Отладка по переписке это особое искусство. Возможны любые варианты :) - Codavr(22.01.2013 13:55)
- Особенно если единицу нулем считать ;) - Vladimir Ljaschko(22.01.2013 15:13)
- Старший коллега "вынудил" зарегистрироваться. Молодой коллега(852 знак., 22.01.2013 12:03)
- Чета я не пойму глубинный смысл конструкции из __disable_interrupt()/__enable_interrupt(), обернутой снаружи в taskENTER_CRITICAL()/taskEXIT_CRITICAL(). Чего добиться-то хотите? Шедулер скрючить? - Lightelf(24.01.2013 09:05)
- Надеть презерватив на свечку. Явные следы последовательного исключения всех подозрительных мест в процессе поиска причины. - vmp(24.01.2013 09:40)
- Гы. Такая конструкция сама по себе может быть причиной. Тут или крестик, или трусы. - Lightelf(24.01.2013 12:58)
- Надеть презерватив на свечку. Явные следы последовательного исключения всех подозрительных мест в процессе поиска причины. - vmp(24.01.2013 09:40)
- А если сделать сообщение на символ-другой меньше, нуль появится? - AD(22.01.2013 17:39)
- Только если стоит точка останова. Ситуация не нравится все больше и больше, потому что во внутренней памяти контроллера работает нормально, во внешней (SDRAM) - только с остановом. Тесты SDRAM проходят. - Vladimir Ljaschko(22.01.2013 17:58)
- Может перед остановом прочитать данные? Поступление команды чтения SDRAM приведёт к тому, что на выходе данные появятся спустя некоторое количество тактов — это время называется задержкой (англ. SDRAM latency) - framer(22.01.2013 18:23)
- А если после sprintf сделать несколько записей в левый буфер, тоже расположенный где-то в SDRAM? Или DSB() поставить? - AD(22.01.2013 18:17)
- Либо в SDRAM не работает байтовая запись, либо это шалит кеш (а он есть в этом процессоре?). - vmp(22.01.2013 18:09)
- Только если стоит точка останова. Ситуация не нравится все больше и больше, потому что во внутренней памяти контроллера работает нормально, во внешней (SDRAM) - только с остановом. Тесты SDRAM проходят. - Vladimir Ljaschko(22.01.2013 17:58)
- А если вынести char buffer[512 + 1]; из локальной области lpc_printf или сделать динамическое выделение памяти под buffer, что нибудь измениться? - framer(22.01.2013 13:34)
- А если так sprintf(buffer, "$s", "Test message...\n"); Кстати буфер дебагером смотришь как набор байтов или как строку? - Codavr(22.01.2013 12:35 - 12:38)
- (char *) из sprintf'а уберите. Что-то изменилось? - Ксения(22.01.2013 12:34)
- все работает, если пройти в спринтфе по шагам. Худший вариант. Похоже, нужно все таки знать, как работает FreeRTOS. - Vladimir Ljaschko(22.01.2013 13:16)
- Нуля нет -- а что вместо нуля? ARM, стек растёт вниз. Затирать конец буфера уж точно не может. Покажи sprintf.c здесь (нет IAR). Вариант: таки прерывания не запрещаются? И обработчик портит какой-то регистр (не сохраняется и т.п.) и потому fk0(125 знак., 22.01.2013 13:44)
- Вместо нуля мусор который был до вызова sprintf. В терминал летит мусор + JTAGом вижу в отладчике на точке останова после sprintf. IARовский sprintf: Молодой коллега(369 знак., 22.01.2013 14:31)
- И как именно определяется, что "нуля нет"? Может метод анализа глючный, а со sprintf всё ок? - fk0(22.01.2013 13:45)
- Фигня получается. sprintf засунут между __disable_interrupt и __enable_interrupt(). Ты говоришь, что перед __enable_interrupt() нуля нет. Но как FreeRTOS может вмешаться если прерывания под запретом? Может это проц какой хитрый которому доступен Codavr(23 знак., 22.01.2013 13:33)
- "мопед не мой", LPC4300 - Vladimir Ljaschko(22.01.2013 13:38)
- Там по DMA никто напакостить не может? - vmp(22.01.2013 14:22)
- Больно прецизионно для DMA. Хотя реальность такие фортеля выкидывает. - Codavr(22.01.2013 14:48)
- А там мусор вместо нуля? Попробуй буфер инициализировать чем нить, чтобы убедиться sprintf не пишет или затирается чем-то. Ну там 0xAA допустим. - Codavr(22.01.2013 13:45)
- Там по DMA никто напакостить не может? - vmp(22.01.2013 14:22)
- "мопед не мой", LPC4300 - Vladimir Ljaschko(22.01.2013 13:38)
- Нуля нет -- а что вместо нуля? ARM, стек растёт вниз. Затирать конец буфера уж точно не может. Покажи sprintf.c здесь (нет IAR). Вариант: таки прерывания не запрещаются? И обработчик портит какой-то регистр (не сохраняется и т.п.) и потому fk0(125 знак., 22.01.2013 13:44)
- +1 - Codavr(22.01.2013 12:38)
- Нет, ичего не изменилось. - Молодой коллега(22.01.2013 13:25)
- все работает, если пройти в спринтфе по шагам. Худший вариант. Похоже, нужно все таки знать, как работает FreeRTOS. - Vladimir Ljaschko(22.01.2013 13:16)
- А остальное-то в буфере есть? Строка "Test message...\n" туда прописалась? - Ксения(22.01.2013 12:17)
- Да всё полностью - "Test message...\n" в буфере лежит как должно быть. - Молодой коллега(22.01.2013 12:22)
- Под FreeRtos надо смотреть на переполнение стека для таска. Можно проверить этим uxTaskGetStackHighWaterMark. - framer(22.01.2013 12:15)
- Я допускаю что где-то стек переполняется и что-то портится, но сразу после sprintf должно быть всё в порядке. Сейчас всего одна задача и стека для нее выделено с 5икратным запасом. - Молодой коллега(22.01.2013 12:30)
- а сколько выделили, какой STACK_SIZE в параметрах линкера? irnt(44 знак., 22.01.2013 20:35)
- Я допускаю что где-то стек переполняется и что-то портится, но сразу после sprintf должно быть всё в порядке. Сейчас всего одна задача и стека для нее выделено с 5икратным запасом. - Молодой коллега(22.01.2013 12:30)
- Чета я не пойму глубинный смысл конструкции из __disable_interrupt()/__enable_interrupt(), обернутой снаружи в taskENTER_CRITICAL()/taskEXIT_CRITICAL(). Чего добиться-то хотите? Шедулер скрючить? - Lightelf(24.01.2013 09:05)
- да-да, я тоже вспомнил эти слова "Этого не может быть, потому что не может быть никогда" ;) - Vladimir Ljaschko(22.01.2013 11:54)
- Если _formatted_write принимает s приведённое к void*, то внутри функции просматриватся говнокод -- арифметика на void* указателями вообще не очень-то допустима... - fk0(22.01.2013 13:55)