Почему передается некорректный адрес указателя в функцию?
Разрабатываю для STM32 на Visual Studio, отладку произвожу при помощи плагина VisualGDB. Компилятор MInGW 12.3, отладчик OpenOCD.
Упрощенная структура моего проекта:
Суть проблемы: Когда я вызываю функцию "ModesInit()" (там она инициализирует струкру "button s1", исходники ниже) в main функции, в SimpleButton_Check(&s1) влетает левый адрес, а не адрес указателя переменной s1. ОДНАКО, когда я просто копирую код внутри "ModesInit()" и всталяю его в main функцию, все работает нормально.
Ниже приведены исходники в упрощенном варианте (без настроек тактирования и т.п.)
main.c
#include "main.h" int main(void) { ModesInit(); while(true) { if (SimpleButton_Check(&s1) == true) { modeSelector++; } } } |
#include "main.h" int main(void) { ModesInit(); while(true) { if (SimpleButton_Check(&s1) == true) { modeSelector++; } } }
main.h
#pragma once #include <stdbool.h> #include "ModeDriver.h" |
#pragma once #include <stdbool.h> #include "ModeDriver.h"
ModeDriver.h
#pragma once #include <stdint.h> #include "SimpleButton.h" #define S1_BUS GPIOA #define S1_PIN 9 #define S1_MODE 0 // 1 - Считается что кнопка нажата по повышению напряжения, 0 - по понижению static uint8_t modeSelector; static button s1; void ModesInit(void); |
#pragma once #include <stdint.h> #include "SimpleButton.h" #define S1_BUS GPIOA #define S1_PIN 9 #define S1_MODE 0 // 1 - Считается что кнопка нажата по повышению напряжения, 0 - по понижению static uint8_t modeSelector; static button s1; void ModesInit(void);
ModeDriver.c
#include "ModeDriver.h" void ModesInit(void) { modeSelector = 0; SimpleButton_Init(&s1, S1_BUS, S1_PIN, S1_MODE); } |
#include "ModeDriver.h" void ModesInit(void) { modeSelector = 0; SimpleButton_Init(&s1, S1_BUS, S1_PIN, S1_MODE); }
SimpleButton.h
#pragma once #include <stdint.h> #include <stdbool.h> #include <string.h> #include "stm32f10x_gpio.h" // ============================= НАСТРОЙКИ ============================= #define Sn_TRIGGER_DELAY 20000 // ~60к = 1 мс. Сколько кнопка должна поймать нажатий чтобы активироваться (Защита от дребезга) // ===================================================================== typedef struct button { const GPIO_TypeDef *GPIO_home; // Шина uint16_t pinBit; // Пин с учетом смещения // TODO: Надо бы сделать конст (он мешает в функции инита)? bool modeUp; // 1 - Считается что кнопка нажата по повышению напряжения, 0 - по понижению // TODO: Надо бы сделать конст (он мешает в функции инита)? uint16_t triggerConter; // Счетчик триггеров uint16_t successCounter; // Счетчик сколько раз счетчик триггеров переполнился uint16_t successInputs; // Сколько успешных циклов отсчета нажатий прошла кнопка (результат successCounter после отжатия) } button; void SimpleButton_Init(button *b, const GPIO_TypeDef *GPIO_home, const uint16_t pinNum, const bool modeUp); bool SimpleButton_Check(button *b); // 1 - Данные можно забирать #define SimpleButton_GetResult(b) b.successInputs // Макрос-функция для забора результата |
#pragma once #include <stdint.h> #include <stdbool.h> #include <string.h> #include "stm32f10x_gpio.h" // ============================= НАСТРОЙКИ ============================= #define Sn_TRIGGER_DELAY 20000 // ~60к = 1 мс. Сколько кнопка должна поймать нажатий чтобы активироваться (Защита от дребезга) // ===================================================================== typedef struct button { const GPIO_TypeDef *GPIO_home; // Шина uint16_t pinBit; // Пин с учетом смещения // TODO: Надо бы сделать конст (он мешает в функции инита)? bool modeUp; // 1 - Считается что кнопка нажата по повышению напряжения, 0 - по понижению // TODO: Надо бы сделать конст (он мешает в функции инита)? uint16_t triggerConter; // Счетчик триггеров uint16_t successCounter; // Счетчик сколько раз счетчик триггеров переполнился uint16_t successInputs; // Сколько успешных циклов отсчета нажатий прошла кнопка (результат successCounter после отжатия) } button; void SimpleButton_Init(button *b, const GPIO_TypeDef *GPIO_home, const uint16_t pinNum, const bool modeUp); bool SimpleButton_Check(button *b); // 1 - Данные можно забирать #define SimpleButton_GetResult(b) b.successInputs // Макрос-функция для забора результата
SimpleButton.c
#include "SimpleButton.h" void SimpleButton_Init(button *b, const GPIO_TypeDef *GPIO_home, const uint16_t pinNum, const bool modeUp) { memset(b, 0x0, sizeof(button)); // Очищаем от лишнего b->GPIO_home = GPIO_home; b->pinBit = (uint16_t)(0b1 << pinNum); b->modeUp = modeUp; } bool SimpleButton_Check(button *b) { bool isPortActive = b->GPIO_home->IDR & b->pinBit; // Напряжение на порту есть? if ((isPortActive && b->modeUp) || (!isPortActive && !(b->modeUp))) { // Если есть напряжение на порт, а режим выбран "срабатывание по возрастанию", ИЛИ нет напряжения, а режим "по понижению" if (++b->triggerConter > Sn_TRIGGER_DELAY) { // Если число тактов достаточное b->triggerConter = 0; b->successCounter++; // То это не залипание, а нажатие } } else { if (b->successCounter > 0) { // Ты отжал кнопку, и это не дребезг? b->successInputs = b->successCounter; b->successCounter = 0; return true; // Можно забирать } b->triggerConter = 0; } return false; // Данные не готовы или не обработаны } |
#include "SimpleButton.h" void SimpleButton_Init(button *b, const GPIO_TypeDef *GPIO_home, const uint16_t pinNum, const bool modeUp) { memset(b, 0x0, sizeof(button)); // Очищаем от лишнего b->GPIO_home = GPIO_home; b->pinBit = (uint16_t)(0b1 << pinNum); b->modeUp = modeUp; } bool SimpleButton_Check(button *b) { bool isPortActive = b->GPIO_home->IDR & b->pinBit; // Напряжение на порту есть? if ((isPortActive && b->modeUp) || (!isPortActive && !(b->modeUp))) { // Если есть напряжение на порт, а режим выбран "срабатывание по возрастанию", ИЛИ нет напряжения, а режим "по понижению" if (++b->triggerConter > Sn_TRIGGER_DELAY) { // Если число тактов достаточное b->triggerConter = 0; b->successCounter++; // То это не залипание, а нажатие } } else { if (b->successCounter > 0) { // Ты отжал кнопку, и это не дребезг? b->successInputs = b->successCounter; b->successCounter = 0; return true; // Можно забирать } b->triggerConter = 0; } return false; // Данные не готовы или не обработаны }
Дополнительно:
Ответы:
Потому что переменная со спецификатором static локальна для единицы трансляции. Ты написал static button s1; в заголовочном файле, а это значит, что каждая единица трансляции в которую ты подключил этот файл получит свой собственный, независимый экземпляр переменной s1. Функция ModesInit инициализирует s1 из ModeDriver.o, а s1 из main.o останется неинициализированным.
Исправить это можно заменив static на extern в заголовочном файле, а в одном из исходников добавив определение для переменной -- button s1;.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос


Передача некорректного адреса указателя в функцию может происходить по разным причинам. Одной из возможных причин является неправильное использование указателей в самом исходном коде программы. Например, если указатель не был инициализирован перед передачей его в функцию, то адрес, который он содержит, может быть некорректным.
Еще одной причиной может быть неправильное использование операторов разыменования указателя (*), что может привести к передаче некорректного адреса в функцию. Например, если указатель был разыменован несколько раз или не был разыменован вообще, то адрес, переданный в функцию, может быть некорректным.
Также, передача некорректного адреса указателя в функцию может быть вызвана ошибкой при работе с динамической памятью. Например, если указатель был выделен для массива определенного размера, но в функцию передается адрес элемента, находящегося за пределами выделенной памяти, то это может привести к передаче некорректного адреса.
Кроме того, передача некорректного адреса указателя в функцию может быть вызвана ошибкой в алгоритме программы. Например, если указатель был изменен в процессе выполнения программы, но его новое значение не было корректно передано в функцию, то это может привести к передаче некорректного адреса.
В целом, передача некорректного адреса указателя в функцию может быть вызвана различными ошибками в коде программы, связанными с работой с указателями, динамической памятью или алгоритмами программы. Для избежания подобных ошибок необходимо внимательно следить за работой с указателями и правильно их использовать в своем коде.