std :: stack,pop()的奇怪行为返回相同的值

时间:2018-07-30 06:04:00

标签: c++ arduino stack esp32

我有使用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通知回调)中添加了堆栈:

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

它工作正常。

我在做什么错了?

2 个答案:

答案 0 :(得分:3)

std::stack<uint8_t*> pendingNotification;

您有一堆指针。为了使这一点有意义,您必须为堆栈提供一堆不同的对象来保存指向的指针,并且这些对象必须在您打算使用指针堆栈的时间内保持有效。您的代码无法执行此操作。

除非有充分的理由,否则不要创建指针堆栈。而是创建数据值的堆栈。

答案 1 :(得分:0)

cell.lblRetweet.text = "\(retweerCount as? Int ?? 0)"

将指向局部变量(notificationService->addPendingNotification(messageId); 数组)的指针推到堆栈上。

此局部变量的作用域稍后(在封闭的messageId块结束时)结束。但是堆栈中的指针仍然保留。此时,取消引用此指针将调用undefined behavior,因此当您将指针从堆栈弹出后执行操作时,得到的结果是未定义的行为。

在您的特定情况下,似乎编译器已为所有if实例重用了相同的内存位置,这意味着在推送所有项目之后,该内存位置仍保留最后推送的项目的值。但要重申:这是未定义的行为,您不应依赖此。

相反,可以将 value 的副本推入堆栈,或者将指针推入堆栈到内存中,该内存将在指针(堆栈)的生命周期内保持分配状态。