Почему передается некорректный адрес указателя в функцию?

Ссылка скопирована
1 ответ

Разрабатываю для 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;.

Нужно решить такую задачу?

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

Заказать помощь
Лучший ответ
1
Артём Dev Ответ

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

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

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

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

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

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно