Странное поведение с std :: stack, pop () возвращает то же значение

У меня есть класс, который использует std::stack:

class NotificationService{
public:
void addPendingNotification(uint8_t *uuid);
uint8_t* getNextPendingNotification();
void popPending();
private:
std::stack<uint8_t*> pendingNotification;
};

void NotificationService::addPendingNotification(uint8_t *uuid) {
pendingNotification.push(uuid);
Serial.print("Insert to stack: ");
Serial.print(uuid[0]);
Serial.print(uuid[1]);
Serial.print(uuid[2]);
Serial.println(uuid[3]);
}

uint8_t *NotificationService::getNextPendingNotification() {
if (pendingNotification.size() > 0) {
uint8_t *uuid = pendingNotification.top();
Serial.println(*uuid);
pendingNotification.pop();
return uuid;
} else {
return NULL;
}
};

void NotificationService::popPending(){
while (!pendingNotification.empty())
{
uint8_t *uuid = pendingNotification.top();
Serial.print(uuid[0]);
Serial.print(uuid[1]);
Serial.print(uuid[2]);
Serial.println(uuid[3]);
pendingNotification.pop();
}
}

Я добавляю в мой основной код (BLE Notification Callback):

static void NotificationSourceNotifyCallback(
BLERemoteCharacteristic *pNotificationSourceCharacteristic,
uint8_t *pData,
size_t length,
bool isNotify)
{
if (pData[0] == 0)
{
uint8_t messageId[4] = {pData[4], pData[5], pData[6], pData[7]};
switch (pData[2])
{
//Incoming Call
case 1:
{
notificationService->addPendingNotification(messageId);
}
/** code **/
}

Все работает нормально, пока я не хочу выталкивать элементы из стека, тогда каждый элемент имеет одинаковое значение (последний вставленный элемент).

Серийный журнал печати:

Insert to stack: 8000
Insert to stack: 32000
Insert to stack: 19000
Insert to stack: 44000
Insert to stack: 4000
Pop whole stack:
4000
4000
4000
4000
4000

Поэтому я пытаюсь написать подобный код в онлайн-компиляторе:

http://cpp.sh/7hv4

И это прекрасно работает.

Что я делаю неправильно?

-1

Решение

std::stack<uint8_t*> pendingNotification;

У вас есть стопка указателей. Чтобы это имело смысл, вам нужно иметь кучу различных объектов для стека, на которые будут помещаться указатели, и эти объекты должны оставаться действительными до тех пор, пока вы намереваетесь использовать стек указателей. Ваш код этого не делает.

Не создавайте стопки указателей, если у вас нет для этого веских причин. Вместо этого создайте стеки значений данных.

3

Другие решения

notificationService->addPendingNotification(messageId);

толкает указатель на локальную переменную ( messageId массив) на стек.

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

В вашем конкретном случае кажется, что компилятор повторно использовал одну и ту же область памяти для всех messageId экземпляры, что означает, что после нажатия всех элементов это место в памяти по-прежнему содержит значение последнего нажатого элемента. Но повторим: это неопределенное поведение, и вы не должны на это полагаться.

Вместо этого, либо нажмите копию значение на стек, или поместите указатель на стек в память, которая останется выделенной на время жизни указателя (стека).

0

По вопросам рекламы [email protected]