stack pop() 导致“引用绑定到未对齐的地址”错误

Posted

技术标签:

【中文标题】stack pop() 导致“引用绑定到未对齐的地址”错误【英文标题】:stack pop() causes "reference binding to misaligned address" error 【发布时间】:2020-08-07 21:03:30 【问题描述】:

我正在尝试为这个 leetcode 问题编写解决方案https://leetcode.com/problems/maximum-frequency-stack/

class FreqStack 
public:
    
   
    map<int, int>mp;
    map<int, stack<int>, greater<int>>st;
    FreqStack() 
        
    
    
    void push(int x) 
        mp[x]++;
        st[mp[x]].push(x);
        
       
    
    
    int pop() 
        stack<int>&v=st.begin()->second;
        
        int t=v.top();
        
        
        if(!v.empty())
        v.pop();
        
        else
            st.erase(st.begin());
        
       
        return t;
    
;

为什么

v.pop()

导致“引用绑定到未对齐的地址”错误?

【问题讨论】:

这似乎无关,但您在假设堆栈不为空之后检查堆栈是否为空。 是的,我知道我只是在尝试不同的方法,看看是否可以让错误消失 调用代码是做什么的? .push(0) 然后是 .pop() 也不是 _GLIBCXX_DEBUG 的地址清理程序我什么也没得到。 恐惧shotgun debugging。它不仅经常使事情变得更糟,而且如果问题确实消失了,它会更难准确地确认您为解决问题所做的工作。如果您不知道修复是什么以及它为什么起作用,那么您可能只是隐藏了问题并移到了它出现的地方。 【参考方案1】:

这不是上述答案中的参考 - 您需要参考才能实际更改 st.如果您不将 v 声明为引用,您最终只会在本地对 v 进行更改,而不是对 st 进行更改。

使用 leetcode 中的示例,在所有推送之后,st[3] 应该有一个包含[5] 的堆栈。在第一次弹出时,该堆栈不为空,因此我们将其弹出。所以st[3] 应该是一个空栈。然后在下一次pop中,v = st.begin() -&gt; second会返回这个空栈,所以pop/top失败。这就是为什么评论流行语或使 v 不是参考在解决问题方面有效,但实际上并没有做任何功能方面的事情。

您需要做的是:弹出后,如果它是一个空堆栈,您需要从 st.所以你的弹出代码看起来像这样

    stack<int>&v=st.begin()->second;
    
    int t=v.top();
    
    
    if(!v.empty())
    v.pop();
    

    if (v.empty()) 
        st.erase(st.begin());
    
   
    return t;

我所做的唯一更改是将 else 变成 if。我希望在 v 不是空的情况下有 t = v.top() ,但是由于我们在堆栈为空时删除频率,所以我们应该被覆盖(v 永远不应该为空)。那应该可以解决您的问题-但这不是 leetcode 问题的正确答案。让你自己弄清楚。

【讨论】:

【参考方案2】:

stack&lt;int&gt;&amp;v=st.begin()-&gt;second; 这里可能有问题,也许尝试在不使用参考的情况下实现你的算法。

从技术上讲,我猜您将指针引用到尚不存在的内存的一部分,并且您正在获得一个 UB,因为您将继续阅读错误。

如果您删除&amp;,您会发现您的代码没有错误。但是,它会输出部分错误的结果。


除此之外,我们还可以使用unordered_map

这将通过:

// This block might trivially optimize the exec time;
// Can be removed;
static const auto __optimize__ = []() 
    std::ios::sync_with_stdio(false);
    std::cin.tie(NULL);
    return 0;
();


// Most of headers are already included;
// Can be removed;
#include <cstdint>
#include <unordered_map>
#include <stack>
#include <algorithm>

static const struct FreqStack 
    using SizeType = std::uint_fast32_t;
    FreqStack() 
    std::unordered_map<SizeType, SizeType> frequencies;
    std::unordered_map<SizeType, std::stack<SizeType>> mapstack;
    SizeType max_fr = 0;

    const void push(const int x) 
        max_fr = std::max(max_fr, ++frequencies[x]);
        mapstack[frequencies[x]].push(x);
    


    const int pop() 
        const auto top = mapstack[max_fr].top();
        mapstack[max_fr].pop();

        if (mapstack[frequencies[top]--].empty()) 
            --max_fr;
        

        return top;
    

;


参考文献

更多详细信息,请参阅Discussion Board,您可以在其中找到大量解释清楚且公认的解决方案,其中包含多种languages,包括高效算法和渐近time/space 复杂性分析1,2.

【讨论】:

“可能这里有问题”的答案并不让人放心。那行代码当然是一个危险信号,但这不足以解释错误。 我不能。那条线是一个危险信号,但我没有看到任何不正确的地方。

以上是关于stack pop() 导致“引用绑定到未对齐的地址”错误的主要内容,如果未能解决你的问题,请参考以下文章

如何将参数绑定到未准备好的查询?

如何修复:编译 SELECT 查询时检测到未定义的绑定

如何允许kendo网格绑定到未定义的字段

错误:从 Bookshelf.js save() 编译 SELECT 时检测到未定义的绑定

使用递归实现 Stack 的 Pop 方法

用两个栈实现队列的POP和PUSH操作