指向堆栈容器的指针在取消引用时导致程序崩溃
Pointer to stack containers cause program to crash when dereferenced
我有一个使用标准容器 vector
、pair
和 stack
的程序。我有一个 std::pair
类型的向量数组,其元素被推入 std::stack
。我有一个函数可以打印三个堆栈的内容,其中两个是空的。第一个堆栈打印正常,但最初传递为空的其他两个堆栈导致 Visual Studio 抛出错误:
Exception thrown: read access violation. _Parent_proxy was 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;
}
stack_array
定义为
stack<pair<int, char>>* stack_array[] = {&stackA, &stackB, &stackC};
所以 *stack_array
是 stack_array
的第一个元素,即 &stackA
。然后在函数 print
中,您使用 &stackA
作为 stack<pair<int, char>>
的数组。那是未定义的行为。
_stack[0]
工作正常,因为它是 stackA
。 _stack[1]
和 _stack[2]
不正确
你似乎觉得这个功能
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;
我有一个使用标准容器 vector
、pair
和 stack
的程序。我有一个 std::pair
类型的向量数组,其元素被推入 std::stack
。我有一个函数可以打印三个堆栈的内容,其中两个是空的。第一个堆栈打印正常,但最初传递为空的其他两个堆栈导致 Visual Studio 抛出错误:
Exception thrown: read access violation. _Parent_proxy was 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;
}
stack_array
定义为
stack<pair<int, char>>* stack_array[] = {&stackA, &stackB, &stackC};
所以 *stack_array
是 stack_array
的第一个元素,即 &stackA
。然后在函数 print
中,您使用 &stackA
作为 stack<pair<int, char>>
的数组。那是未定义的行为。
_stack[0]
工作正常,因为它是 stackA
。 _stack[1]
和 _stack[2]
不正确
你似乎觉得这个功能
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;