jenya7 0 4 января, 2023 Опубликовано 4 января, 2023 (изменено) · Жалоба Как можно знать по каким адресам расположаться локальные переменные на стеке при вхождении в функцию? Или это в принципе невозможно? Изменено 4 января, 2023 пользователем haker_fox Исправил опечатку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 221 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба Например, с помощью оператора получения адреса переменной "&". Можно определить относительные адреса в стеке с помощью изучения ассемблерного кода функции. Всё зависит от целей и задач, которые вы не сформулировали. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Variant99 7 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба Можно еще и в отладчике посмотреть Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба 1 час назад, jenya7 сказал: расположаться Что сделаютЬ? 1 час назад, jenya7 сказал: на стаке А чего сразу не "на стацке"? Надеюсь, вы понимаете, что в общем случае при каждом входе в функцию эти адреса будут разные? Что-то мне подсказывает, что вы снова закатываете Солнце вручную и пытаетесь реализовать va_arg Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба On 1/4/2023 at 9:41 AM, Сергей Борщ said: Надеюсь, вы понимаете, что в общем случае при каждом входе в функцию эти адреса будут разные? Что-то мне подсказывает, что вы снова закатываете Солнце вручную и пытаетесь реализовать va_arg разные? почему? что поменялось между входами? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба 1 минуту назад, jenya7 сказал: что поменялось между входами? Вы действительно не понимаете или издеваетесь? void a() { int i; printf("addr = %p\n", &i); } void b() { volatile int ii = 0; a(); } void test() { a(); b(); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба On 1/4/2023 at 9:48 AM, Сергей Борщ said: Вы действительно не понимаете или издеваетесь? void a() { int i; printf("addr = %p\n", &i); } void b() { volatile int ii = 0; a(); } void test() { a(); b(); } ну и? тут статика, не вижу почему адреса должны измениться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба Потому что при первом вызове функции a() стек условно пустой, а при втором вызове на стеке уже лежит переменная ii из функции b(). Что вы понимаете под понятием "статика" - мне неведомо. Ну погоняйте этот код под отладчиком до пониамния, что ли. Я пас. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Variant99 7 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба Почему "стацк" выдает разные адреса для переменных одной ф-ции? Да потому, что в первый раз фукнция вызвалась из main, когда "стацк" находился почти в его начале, а во второй раз эта же функция вызвалась из функции Foo, которая была вызвана из другой ф-ции OtherFoo, и "стацк" для вашей фукнции сместился уже подальше от его начала, потому как на "стацке" лежат "стацки" этих двух функций. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба On 1/4/2023 at 9:53 AM, Сергей Борщ said: Потому что при первом вызове функции a() стек условно пустой, а при втором вызове на стеке уже лежит переменная ii из функции b(). Ну погоняйте этот код под отладчиком до пониамния, что ли. Я пас. я понимаю. я говорю про общий случай. мне нужен весь стак до выхода из test(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба Ничего не понял. В общем случае глубина стека на момент вызова функции может быть любой и, соотвественно, любым может быть адрес переменной на стеке. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 января, 2023 Опубликовано 4 января, 2023 (изменено) · Жалоба On 1/4/2023 at 9:02 AM, makc said: Например, с помощью оператора получения адреса переменной "&". Можно определить относительные адреса в стеке с помощью изучения ассемблерного кода функции. Всё зависит от целей и задач, которые вы не сформулировали. очень непонятный баг. я получаю данные в буфер. периодически (раз в 163 секунды) данные принимают мусорные значения. void buffcpy_cont(uint16_t *DataBuffer, uint16_t dataPtr, uint16_t lenght) { } void save_data(uint16_t* DataBuffer, uint16_t command) { } uint16_t check_new_message(void) { uint16_t l_uiDataBuffer[32]; uint16_t l_uiTempDataP = 0, l_uiDataSize = 0; buffcpy_cont(l_uiDataBuffer, l_uiTempDataP, l_uiDataSize); save_data(l_uiDataBuffer, l_uiCommandWord); } чттоб понять где ломаются данные я посылаю нулевые данные и поставил ловушки void buffcpy_cont(uint16_t *DataBuffer, uint16_t dataPtr, uint16_t lenght) { } void save_data(uint16_t* DataBuffer, uint16_t command) { //trap 2 if (DataBuffer[15] != 0) lock=1; } uint16_t check_new_message(void) { uint16_t l_uiDataBuffer[32]; uint16_t l_uiTempDataP = 0, l_uiDataSize = 0; buffcpy_cont(l_uiDataBuffer, l_uiTempDataP, l_uiDataSize); //trap 1 if (l_uiDataBuffer[15] != 0) lock=1; save_data(l_uiDataBuffer, l_uiCommandWord); } срабатывает вторая ловушка. то есть данные ломаются при передаче буфера в функцию save_data. я сделал буфер l_uiDataBuffer глобальным и проблема исчезла. но от меня требуют объяснений. что интересно - посылка данных каждые 160 милисек - 163s/160ms = 1024 - как раз размер стака. может конечно просто совпадение. ещё дополнение - система давно работает в лабораторных условиях но там её гоняют в режиме stress test - посылки данных каждые 20 милисек. проблема проявилась в полевых условиях - при посылках каждые 160 милисек. Изменено 4 января, 2023 пользователем jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Variant99 7 4 января, 2023 Опубликовано 4 января, 2023 (изменено) · Жалоба Иллюстрирую поведение стека при вызовах функций: Вначале код находится в main, а указатель вершины стека находится в его начале: Спойлер Понятно, да? Теперь вызываем из main функцию Test, указатель стека смещается на шаг назад (под шагом имею ввиду совокупность данных, располагаемых в стеке фукнции): Спойлер Видите, где лежат переменные a, b, c? Запомнили? При выходе из фукнции Test указатель стека вернется в первоначальное положение: Спойлер Теперь вызовем из main функцию OtherFoo(): указатель стека сместится на шаг назад, на те адреса, которые принадлежали ранее вызывавшейся функции Test, они будут ПЕРЕЗАПИСАНЫ переменными функции OtherFoo! Спойлер Видите - там, где раньше лежало значение 00000001 от фукнции Test, теперь помещено значение 000001F4. Затем из OtherFoo вызывается функция Foo, и только уже из нее вызовется наша Test. Смотрите теперь ГДЕ будут лежать переменные a, b, 😄 Узрели? Переменные те же самые, функция та же самая, но адреса на "стацке" этих переменных - уже, черт возьми, другие. Понятно теперь как работает стек? И самое важное из этого следствие: нельзя возвращать из функции адреса локальных нестатичных переменных, которые лежат в стеке функции, потому как при выходе из функции эти данные перестают быть актуальными и могут быть затерты другими функциями, в том числе и вызываемыми из возникшего в этот момент ПРЕРЫВАНИЯ! Если хотите, чтобы локальные переменные в фукнции сохраняли свою актуальность после выхода из функции, вы должны эти переменные объявить как static, тогда они будут расположены не на "стацке", а в другой области памяти и не будут затерты. Изменено 4 января, 2023 пользователем Variant99 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба On 1/4/2023 at 10:28 AM, Variant99 said: И самое важное из этого следствие: нельзя возвращать из функции адреса локальных нестатичных переменных, которые лежат в стеке функции, потому как при выходе из функции эти данные перестают быть актуальными и могут быть затерты другими функциями, в том числе и вызываемыми из возникшего в этот момент ПРЕРЫВАНИЯ! Если хотите, чтобы локальные переменные в фукнции сохраняли свою актуальность после выхода из функции, вы должны эти переменные объявить как static, тогда они будут расположены не на "стацке", а в другой области памяти и не будут затерты. это не мой случай. или если произойдёт прерывание между функциями это может затереть переменную? buffcpy_cont(l_uiDataBuffer, l_uiTempDataP, l_uiDataSize); //тут прерывание save_data(l_uiDataBuffer, l_uiCommandWord); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Variant99 7 4 января, 2023 Опубликовано 4 января, 2023 · Жалоба Когда произойдёт прерывание - неизвестно. На то оно и прерывание, чтобы прерывать работу в любое время в любом месте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться