我在这里张贴了两个片段。 第一个是在释放内存时给我分段错误。第二个工作正常。
1)
int main()
{
char* ch = new char;
ch = "hello";
cout << "\n " << ch << endl;
delete[] ch; ////OR delete ch; ---> have tried both
return 0;
}
2)
int main()
{
char* ch = new char;
cin >> ch;
cout << "\n " << ch << endl;
delete[] ch; ///OR delete ch /// Both are working fine....
return 0;
}
有人可以告诉我为什么第一个失败的分段错误,第二个与delete
和delete[]
一起正常工作。因为对我而言,这两个程序看起来都是一样的。
答案 0 :(得分:2)
new char
只生成1个字符(不是1个字符的数组,为此使用new char[1]
)
所以删除[]不适用
在第一个例子中,你用指向字符串&#34; hello&#34;的指针覆盖指向你分配的1个字符的指针。 - 删除此字符串(因为它是静态内存)将导致sesgfault修改
int main()
{
char* ch = new char; // ch points to 1 character in dynamic memory
ch = "hello"; // overwrite ch with pointer to static memory "hello"
cout<<"\n "<<ch<<endl; // outputs the content of the static memory
delete[] ch; // tries to delete static memory
return 0;
}
答案 1 :(得分:2)
这两个例子都存在问题:
char* ch = new char;`
ch = "hello";`
new
返回指向动态分配内存的地址。您必须保存此返回值,以便稍后可以发出delete
。上面的代码用“hello”(字符串文字)覆盖了这个值。您现在已经丢失了该值,因此无法使用正确的值调用delete
。
第二个例子,即使你说“工作正常”仍然有问题。
char* ch = new char;`
delete[] ch; ///OR delete ch /// Both are working fine....`
使用了delete
的错误形式。您已使用new
分配,因此您必须使用delete
而不是delete[]
取消分配。它的工作方式如下:new
- &gt; delete
,new[]
- &gt; delete[]
。
与大多数其他语言不同,如果您违反C ++规则,损坏内存,覆盖缓冲区等,没有保证您的程序崩溃,错误等等。让你知道你做错了什么。
在这种情况下,您很幸运char*
等简单类型不会受到使用错误形式delete
的影响。但是,如果更改编译器,运行时设置等,则无法保证这始终有效。
答案 2 :(得分:1)
在第一个中,您将指针更改为指向字符串文字:
ch = "hello";
字符串文字是静态数组,因此不能删除。
第二个错误至少有两个原因:
delete
而不是delete[]
cin>>ch
(很可能)会读取多个字符,但您只为一个字符分配空间。这两种行为都会导致未定义的行为,这可能表现为可见的错误,或者可能看起来像#34;工作正常&#34; - 但是当你最不期望它时可能会失败。
要分配数组,请使用new char[SIZE]
;但即使这样,你也无法阻止用户输入过多的输入并溢出缓冲区。
除非你自己教会如何处理原始记忆(这是一种黑暗的艺术,除非绝对必要,否则最好避免),你应该坚持为你管理记忆的高级类型:
std::string string;
string = "hello";
std::cout << string << '\n';
std::cin >> string;
std::cout << string << '\n';
答案 3 :(得分:1)
每个问题都存在一些问题,即您在尝试分配字符数组时只分配一个字符。
在第一个示例中,您还要分配单个字符,然后将指针重新分配给字符数组 - ch = "hello"
将不复制字符串,只需重新分配指针。您对delete []的调用将尝试删除未分配堆的字符串,因此会出现seg错误。而且你也在泄漏你分配的字符。
答案 4 :(得分:1)
以下是两个片段的错误:
第一个片段:
char* ch = new char; ch = "hello";
将字符串文字分配给非const char指针是不合法的。
此外,在调用new
后立即重新指定指针。 new
返回的原始值现在永远丢失,并且在程序期间不能免费。这被称为内存泄漏。
delete[] ch;
您尝试取消分配字符串文字。这会使您的程序崩溃。您只能从delete
获得的new
和delete[]
指针获得new[]
个指针。删除任何其他内容都有未定义的行为。
第二个片段:
cout<<"\n "<<ch<<endl;
ch
指向单个字符,而不是零终止字符数组。将此指针传递给cout
具有未定义的行为。您应该使用cout << *ch;
打印该单个字符,或确保ch
指向一个零终止的字符数组。
delete[] ch;
您使用new
分配,必须使用delete
取消分配。在这里使用delete[]
具有未定义的行为。
两者都工作正常......
“正常工作”是未定义行为的一种可能结果,就像运行时错误一样。
要回答这个问题,两个片段都不正确。第一个崩溃因为你运气好,第二个似乎工作因为你运气不好。
解决方案:使用std::string
。
答案 5 :(得分:1)
您的计划中有多处错误。
在第一个程序中,您没有删除动态分配的内容,而是删除静态分配的字符串&#34; hello&#34;。实际上当你执行ch =&#34;你好&#34;你没有在错误分配的缓冲区中复制字符串&#34; new char&#34; (这个新的只是分配一个字符,而不是你正在寻找的),但你使指针ch指向字符串的开头&#34;你好&#34;位于不可写内存中的某个位置(通常该字符串直接指向可执行文件)。因此删除操作试图释放无法解除分配的内容。所以第一个程序被重写如下:
int main()
{
const char* ch = "hello";
cout<<"\n "<<ch<<endl;
return 0;
}
或喜欢
int main()
{
char* ch = new char[strlen("hello")+1];
strcpy( ch, "hello");
cout<<"\n "<<ch<<endl;
delete[] ch; // with square brackets, it's an array
return 0;
}
答案 6 :(得分:0)
你应该使用类似的东西:
char * ch = new char [6];
strcpy(ch,“hello”);
...
删除[] ch;