std::stack的奇怪行为,pop()返回相同的值
Strange behaviour with std::stack, pop() returns same value
我有一个使用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
而且效果很好。
我做错了什么?
std::stack<uint8_t*> pendingNotification;
你有一堆指针。为了实现这一点,堆栈中必须有一堆不同的对象来保存指针,并且只要您打算使用指针堆栈,这些对象就必须保持有效。你的代码不能做到这一点。
除非你有充分的理由,否则不要创建指针堆栈。相反,创建数据值堆栈。
notificationService->addPendingNotification(messageId);
将指向局部变量(messageId
数组(的指针推送到堆栈上。
这个局部变量的作用域在稍后的某个时刻结束(只要封闭的if
块结束(。但是堆栈中的指针仍然存在。此时,取消引用该指针会调用未定义的行为,因此当您在将指针从堆栈中弹出后执行此操作时,得到的结果是未定义行为。
在您的特定情况下,编译器似乎为所有messageId
实例重新使用了相同的内存位置,这意味着在推送所有项之后,该内存位置仍然保存最后一个推送项的值。但是要重新迭代:这是未定义的行为,您不应该依赖于此。
相反,将值的副本推送到堆栈上,或者将指针推送到堆栈中,指向在指针(堆栈(的生存期内仍将分配的内存。
相关文章:
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 什么时候在C++中返回常量引用是个好主意
- 你能重载对象变量名本身返回的内容吗
- 为什么 Serial.println(<char[]>);返回随机字符?
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何获取std::result_of函数的返回类型
- QueryWorkingSet总是返回false
- (C++)分析树以计算返回错误值的简单算术表达式
- 访问者访问变体并返回不同类型时出错
- 如何返回一个类的两个对象相加的结果
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- lower_bound()返回最后一个元素
- std::stack的奇怪行为,pop()返回相同的值
- std::queue::size() 可以在 size() == 0 的 pop() 之后返回一个巨大的数字
- 计算后缀表达式.pop() 返回不正确的值来计算函数
- 现在可以队列::pop返回一个值
- 为什么 top() 的返回值在调用 pop() 后会发生变化?
- 在无锁的pop()中使用引用参数返回值的缺点
- 为什么不在pop之后运行task并返回true呢?
- 数据结构-在C++中,如果没有pop()函数,我如何返回堆栈的第二个元素