我有一个整数数组排序程序,但是我有一个问题:每当我运行程序时,我有时会得到一个“变量'数字'周围的堆栈已损坏”消息,有时它只是重复打印出数字8。这是我的代码(在Visual C ++ 2010中编译):
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;
void swap(int *x, int *y)
{
int tmp=0;
tmp = *x;
*x = *y;
*y = tmp;
tmp = 0;
}
int main()
{
int numbers[13] = {8,16,23,487,2,301,48,0,13,10,644,12};
int size = sizeof(numbers) / sizeof(int);
//sort
int i = 0;
int* a = &numbers[0];
int* b = &numbers[1];
while(i < size){
if(*a > *b){
swap(a, b);
}
*a++;
*b++;
i++;
}
//Print our results
int loopIterator = 0;
int numToPrint = 0;
while(loopIterator < size){
cout << numbers[numToPrint] << endl;
loopIterator++;
}
system("PAUSE");
}
答案 0 :(得分:2)
首先,您永远不会增加numToPrint
,因此您永远不会打印超过numbers[0]
的值。至少将您的代码更改为:
while(loopIterator < size){
cout << numbers[numToPrint++] << endl;
loopIterator++;
}
其次,由于您的while
循环使用了测试i < size
,因此在循环的最后一次迭代中,您将访问numbers
以外的内存{{1}指针,并可能将该值交换到b
的最后一个槽(即numbers
指向的位置)。您希望将测试更改为a
以避免出现这种情况。例如,如果在i < (size - 1)
您有i == 0
和a = &numbers[0]
,那么到b = &numbers[1]
时,您最终会得到i == 12
和{{ 1}} ... a = &numbers[12]
在此实例中指向的值超过了数组的末尾。根据编译器设置堆栈的方式以及在堆栈上分配b = &numbers[13]
的方式,如果最终b
指向激活记录,这实际上可能对您的程序造成一定的破坏您的numbers
函数的数据结构,并反过来破坏它。
答案 1 :(得分:2)
我假设您正在将数组排序实现为练习。这并没有真正回答你的问题,但我认为我会发布以供参考,无论如何。这是使用STL实现所需结果的一种方法:
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
int numbers[] = { 8, 16, 23, 487, 2, 301, 48, 0, 13, 10, 644, 12 };
size_t const size = sizeof(numbers) / sizeof(numbers[0]);
int * const begin = numbers;
int * const end = numbers + size;
std::sort(begin, end);
std::copy(begin, end, std::ostream_iterator<int>(std::cout, "\n"));
}
答案 2 :(得分:0)
有一件事立即跳出来就是你永远不会增加numToPrint所以它会打印出数字[0],大小次数。
我会将您的打印部分重写为
for (int i = 0; i < size; i++)
cout << numbers[i] << endl;
有了这个,您就可以摆脱代码的打印结果部分,因为上面是一种更干净的方式来做同样的事情。
您收到的错误消息可能是因为您正在写入您不应该触摸的内存部分。这可能是因为错误地使用“sizeof”造成的。它返回数字中的元素数,而不是内存大小。建议检查实际问题的评论,以便正确解决第二个问题。
答案 3 :(得分:0)
这种排序不起作用,因为你只运行一次数字列表,所以它会交换相邻的项目,但它不会对列表进行排序(它是泡泡排序的一半实现)
答案 4 :(得分:0)
我很确定你在这里有一个运算符优先级问题:
*b++;
事实上,编译器应该警告你一个没有副作用的运算符(*
)。
除此之外,指针b
将离开数组的末尾,因为它从元素1开始并且提前size
次,它最终将指向numbers[size+1]
。如果编译器优化掉无用的解除引用,那就不会有问题了,但是在上一次传递中你调用swap(numbers+size-1, numbers+size)
并注销数组的末尾,导致你检测到堆栈损坏。