【问题标题】:Pointer to stack containers cause program to crash when dereferenced指向堆栈容器的指针导致程序在取消引用时崩溃
【发布时间】:2016-06-09 23:22:37
【问题描述】:

我有一个使用标准容器vectorpairstack 的程序。我有一个std::pair 类型的向量数组,其元素被推送到std::stack。我有一个打印三个堆栈内容的函数,其中两个是空的。第一个堆栈打印正常,但最初作为空传递的其他两个堆栈导致 Visual Studio 抛出错误:

抛出异常:读取访问冲突。 _Parent_proxy 是 0xCCCCCCCC。

错误出现在xutility的第165行。

当其他两个堆栈中的任何一个为空或非空时,就会发生这种情况。我不知道是什么导致了这个问题,因为第一个堆栈工作正常,但随后的两个堆栈导致程序崩溃。

在 main.cpp 文件中:

void stackPrint(stack<pair<int, char>> _stack) {
    stack<pair<int, char>> temp_stack;
    for (auto i = _stack; !i.empty(); i.pop()) 
        temp_stack.push(i.top());

    while(!temp_stack.empty()) {
        cout << temp_stack.top().first << ", ";
        temp_stack.pop();
    }
}

void print(stack<pair<int, char>>* _stack) {
    cout << "Stack A: ";
    stackPrint(_stack[0]); // function call executes successfully and stackPrint functions properly
    cout << "B: ";
    stackPrint(_stack[1]); // xutility error happens here at function call, stackPrint never invoked
    cout << "C: ";
    stackPrint(_stack[2]); // same here if B is commented out 
}


int main() {
    stack<pair<int, char>> stackA, stackB, stackC;
    int num = 5;

    vector<pair<int, char>> stack_elements(num);

    for (int i = num - 1; i >= 0; i--) {
        stack_elements[i].first = i;
        stack_elements[i].second ='A';
        stackA.push(stack_elements[i]);
    }

    //stackB.push(stack_elements[1]);
    //stackC.push(stack_elements[1]);

    stack<pair<int, char>>* stack_array[] = {&stackA, &stackB, &stackC};

    print(*stack_array);

    return 0;
}

【问题讨论】:

    标签: c++ pointers exception stack containers


    【解决方案1】:

    你似乎对这个功能有印象

    void print(stack<pair<int, char>>* _stack) {
    

    采用指向堆栈的指针数组,但事实并非如此。只需阅读参数类型:它是指向堆栈的单个指针。这与传递堆栈数组(不是指向堆栈的指针)兼容,因为数组衰减为指针。

    现在看调用站点:

    stack<pair<int, char>>* stack_array[] = {&stackA, &stackB, &stackC};
    
    print(*stack_array);
    

    你有一个指针数组(正如我所说,这个函数不能接受),但你在调用print 时取消引用它。这等同于

    print(stack_array[0]);
    

    所以,您传递了一个指向 stackA 的指针,但 print 假定这是堆栈数组中的第一个元素。 (stackB 和 C 在 stackA 之后声明的事实并不意味着它们形成一个数组,它们仍然是不相关的本地对象。

    您可以更改呼叫站点以符合print 的期望:

    stack<pair<int, char>> stacks[3];
    stack<pair<int, char>> &stackA = stacks[0];
    stack<pair<int, char>> &stackB = stacks[1];
    stack<pair<int, char>> &stackC = stacks[2];
    // ...
    print(stacks)
    

    或更改两者以匹配您现有的 stack_array 类型(注意 **,这是指针数组衰减到的内容)

    void print(stack<pair<int, char>>** _stack);
    // ...
    print(stack_array);
    

    或者停止使用这些具有神奇硬编码长度的衰减数组,并使用

    std::array<std::stack<int,char>, 3> threestacks;
    

    std::vector<std::stack<int,char>> somestacks;
    

    【讨论】:

      【解决方案2】:

      stack_array定义是

      stack<pair<int, char>>* stack_array[] = {&stackA, &stackB, &stackC};
      

      所以*stack_arraystack_array 的第一个元素&amp;stackA。然后在函数print 中使用&amp;stackA 作为stack&lt;pair&lt;int, char&gt;&gt; 的数组。那是未定义的行为。

      _stack[0] 工作正常,因为它是stackA_stack[1]_stack[2] 不正确

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-23
        • 1970-01-01
        • 2015-01-04
        相关资源
        最近更新 更多