Вызов указателя функции приводит к 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

Следовательно, что-то не так с тем, как я использую указатель на функцию (или где-то еще, о чем я даже не думаю). Может ли кто-нибудь дать мне подсказку, с чего я мог бы начать?

, 👍2

Обсуждение

Как определяется обратный вызов? А переменные 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


1 ответ


2

Я нашел проблему. После перемещения обработчиков SubscriptionHandler[] = ... из setup()-метода функция вызывает work. Возможно, обработчики перезаписываются после выхода из области setupfunction. Может ли кто-нибудь подтвердить мою предполагаемую причину?

,

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