Вызов указателя функции приводит к InstrFetchProhibited (ESP32)
У меня есть следующая проблема, которую я не могу решить самостоятельно. Возможно, кто-нибудь из вас мог бы указать мне на проблемы в моем коде, которых я не вижу.
Существует класс под названием communicator, который обрабатывает соединение MQTT. Я использую PubSubClient
в качестве клиента MQTT. Конструктор communicator
выглядит следующим образом. Помимо аргументов подключения, он также получает массив структур SubscriptionHandler
. Эти структуры определяют, на какие разделы следует подписаться, а также указывают на метод обратного вызова. Когда коммуникатор
получает сообщение MQTT, он сравнивает тему с известными и вызывает соответствующий обратный вызов.
Communicator(char * mqttBrokerIP, uint16_t mqttBrokerPort, char *mqttUsername, char * mqttPassword, char * mqttClientHostname, SubscriptionHandler subscriptionHandlers[], int lenHandlers);
Обработчикподписок. определяется следующим образом:
typedef void (*callback)();
struct SubscriptionHandler
{
char *Topic;
callback Callback;
};
Я попробовал следующее: В основном файле я определил два метода для демонстрационных целей:
void enableHandler()
{
Serial.println("enable handler");
}
void disableHandler()
{
Serial.println("disable handler");
}
Коммуникатор
создается в setup()
-методе:
SubscriptionHandler handlers[] = {{&strEnable, enableHandler},
{&strDisable, disableHandler}};
обратный вызов (в communicator.h) typedef void (обратный вызов)();
строки : String strEnable = ("test/" + имя хоста + "/command/enable");
и то же самое для отключения. Они также определены в main.cpp –
Как только коммуникатор
получает сообщение MQTT, ESP32 завершает работу со следующим сообщением:
Guru Meditation Error: Core 1 panic'ed (InstrFetchProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x3ffc9306 PS : 0x00060c30 A0 : 0x8017e97c A1 : 0x3ffb1ed0
A2 : 0x3ffc9306 A3 : 0x3ffc9306 A4 : 0x3ffc9306 A5 : 0x3ffc1318
A6 : 0x3ffb1f44 A7 : 0x00000000 A8 : 0x800d4df0 A9 : 0x3ffb1eb0
A10 : 0x0000000d A11 : 0x0000000b A12 : 0x3ffc24a4 A13 : 0xa98b32f8
A14 : 0x3ffc1318 A15 : 0xff000000 SAR : 0x00000004 EXCCAUSE: 0x00000014
EXCVADDR: 0x3ffc9304 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace: 0x3ffc9306:0x3ffb1ed0 0x4017e979:0x3ffb1f00 0x400e280e:0x3ffb1f20 0x400d4f3e:0x3ffb1f70 0x400d5cff:0x3ffb1f90 0x400e4c45:0x3ffb1fb0 0x400889dd:0x3ffb1fd0
Следовательно, что-то не так с тем, как я использую указатель на функцию (или где-то еще, о чем я даже не думаю). Может ли кто-нибудь дать мне подсказку, с чего я мог бы начать?
@pixelgate, 👍2
Обсуждение1 ответ
Я нашел проблему. После перемещения обработчиков SubscriptionHandler[] = ...
из setup()-
метода функция вызывает work. Возможно, обработчики
перезаписываются после выхода из области setupfunction. Может ли кто-нибудь подтвердить мою предполагаемую причину?
Все, что находится в локальной области видимости (определенной в функции), исчезает после завершения функции. Даже если вы где-то храните указатель на него. Он исчез., @Majenko
- esp32, platformio A fatal error occurred: Packet content transfer stopped (received 8 bytes) *** [upload] Error 2
- Как выбрать альтернативные контакты I2C на ESP32?
- Драйверы для чипа последовательного порта CH9102X
- Как преобразовать форматированный оператор print в строковую переменную?
- ESP32 - "Детектор Браунаута был активирован" при запуске Wi-Fi
- Питание esp32cam от аккумулятора
- Контакты RX и TX на esp32
- ESP32: отключить детектор отключения питания
Как определяется
обратный вызов
? А переменныеstr ...
- что это такое?, @Majenko**обратный вызов**
` typedef void (*обратный вызов)();
* строки *** :
String strEnable = ("test/" + имя хоста + "/command/enable");
` и то же самое для отключения. Они также определены в main.cpp, @pixelgateИ эти strEnable a strDisable строки? Если это массив символов, у вас не должно быть & здесь, и для лучшей читаемости оно должно быть перед именами функций., @KIIV
Вы передаете адрес строкового объекта в указатель char *. Это очень плохо., @Majenko
вы видели это? https://randomnerdtutorials.com/esp32-mqtt-publish-subscribe-arduino-ide/, @jsotola
@Majenko, я действительно не был уверен в этом. Но эта библиотека mqtt использует этот тип данных, поэтому я тоже подумал об ее использовании. Есть ли лучший способ?, @pixelgate
@jsotola, дело в том, что я подписываюсь на несколько тем, и я хочу вызвать метод x класса y, когда получу что-то по теме z. Публикация и подписка работают на примерах, которые я пробовал ранее. Но вызов функции после получения сообщения и определения того, какую функцию вызывать, приводит к сбою., @pixelgate