【发布时间】:2018-07-30 06:04:00
【问题描述】:
我的课程使用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
所以我尝试在在线编译器中编写类似的代码:
而且效果很好。
我做错了什么?
【问题讨论】:
-
我的 猜测(因为您没有显示Minimal, Complete, and Verifiable Example)是您将指针传递给单个变量,因此所有指针在堆栈中指向该单个变量。我建议您为“uuid”创建一种不同的类型,一种可以复制或移动并按值传递的类型。或者也许重用像
std::array<uint8_t, 4>这样的类型? -
检查从每个
top调用返回的地址应该会让您想知道这是怎么可能的。倒计时,看看你通过每个调用推送到notificationService->addPendingNotification(messageId);的内容将确认这一点。更糟糕的是,无论如何,您都在调用未定义的行为。您有效地将 dangling 指针推入堆栈。每次退出if (pData[0] == 0)作用域块时,刚刚压入堆栈的messageId表示的地址不再对解引用有效。而且你有一整堆这样的地址。 -
什么是strack?