好的,我打算安排两个课程。两者都是使用指针和new运算符的动态数组。但似乎并不喜欢删除操作符。
#include <iostream>
int main()
{
int *p;
p = new int[5];
for (int i = 0; i < 5; i++)
{
p[i] = 25 + (i * 10);
std::cout << p[i] << " ";
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
这是第一个节目。它喜欢删除运算符就好了。现在不喜欢删除操作符的程序:
#include <iostream>
int main()
{
int x;
int *p;
p = new int[5];
*p = 4;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
这个程序编译得很好。但是在执行期间,它会抛出一个错误 - free(): invalid pointer: 0xfdb038
..或者该特定执行的内存地址。所以,问题是:
为什么在第二种情况下不能使用删除操作符?
我不想让内存泄漏;我不希望指针悬空。
如果我只是说p = NULL;
,然后是p = 0
,但我相信指针仍悬着?,但我不确定。提前谢谢。
答案 0 :(得分:2)
在第二段代码中查看此循环:
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1; // <--- Here
}
请注意,在此行中,您将写入p
当前指向的内存地址。由于您总是递增p
然后写入,因此您最终会在您为p
分配的区域末尾注销。 (如果我们将pOrig
想象为指向p
最初指向的位置的指针,则会写入pOrig[1]
,pOrig[2]
,pOrig[3]
,pOrig[4]
,和pOrig[5]
,并且最后一次写入超过了该区域的结尾)。这会导致未定义的行为,这意味着任何事情都可能发生。这是坏消息。
此外,delete[]
假定您传入指向您分配的数组的第一个元素的指针。由于您在该循环中已经多次增加p
,因此您尝试delete[]
指针不在分配的数组的基础上,因此问题
要解决此问题,请在递增后不要写入p
,并存储指向分配有new[]
的原始数组的指针,以便您可以释放它而不是修改后的指针{ {1}}。
答案 1 :(得分:0)
您必须grecaptcha.reset();
从delete
获得的指针。但是,在您的第二个代码中,您执行了更改指针的new
。因此,您尝试p++
从delete
和new
崩溃中获得的指针。
要解决此类错误,请不要使用delete
。而是使用new
。由于您永远不需要std::vector<int> p;
,因此您无法忘记new
。
答案 2 :(得分:0)
p
中的问题正在改变p++
。
您应该始终存储(删除)原始指针。像这样:
#include <iostream>
int main()
{
int *original = new int[5];
int *p = original;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
int x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] original;
return 0;
}