[英]Segmentation Fault in deleting char pointer
我在这里发布两个片段。 第一个是在分配内存时给我Segmentation Fault。 第二个工作正常。
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;
}
谁能告诉我为什么第一个失败并出现Segmentation Fault而第二个失败时使用delete
和delete[]
。 因为对我来说,这两个程序似乎相同。
new char
生成正好1个字符(不是1个字符的数组,请使用new char[1]
)
因此delete []不适用
在第一个示例中,您使用指向字符串“ hello”的指针覆盖了指向已分配的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;
}
这两个示例都存在问题:
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
> delete
, new[]
-> delete[]
。
与大多数其他语言不同,如果您违反C ++规则,损坏的内存,覆盖缓冲区等,则无法保证程序会崩溃,出现段错误等,以使您知道自己做错了什么。
在这种情况下,您很幸运,使用错误形式的delete
不会影响诸如char*
类的简单类型。 但是您不能保证如果您更改编译器,运行时设置等,它将始终有效。
在第一个中,您将指针更改为指向字符串文字:
ch = "hello";
字符串文字是静态数组,因此不能删除。
第二个错误至少有两个原因:
delete
不是delete[]
cin>>ch
将(很可能)读取多个字符,但是您仅为一个字符分配了空间。 这两种情况都会导致不确定的行为,这可能会表现为可见错误,或者看起来似乎“工作正常”,但在您最不期望的情况下可能会失败。
要分配数组,请使用new char[SIZE]
; 但是即使如此,您仍不能阻止用户提供过多的输入并溢出缓冲区。
除非您正在教自己如何处理原始内存(这是一门黑手艺,除非绝对必要,否则最好避免这样做),否则您应该坚持为您管理内存的高级类型:
std::string string;
string = "hello";
std::cout << string << '\n';
std::cin >> string;
std::cout << string << '\n';
每种方法都有两个问题,即尝试分配字符数组时仅分配一个字符。
在第一个示例中,您还分配了一个字符,然后将指针重新分配给字符数组ch = "hello"
不会复制字符串,只是重新分配指针。 然后,您对delete []的调用将尝试删除未分配堆的字符串,因此出现段错误。 而且,您还会泄漏您分配的字符。
这两个片段都出了什么问题:
第一个片段:
char* ch = new char; ch = "hello";
将字符串常量分配给非const char指针是不合法的。 另外,您在调用new
之后立即重新分配指针。 现在, new
返回的原始值将永远丢失,并且在程序执行期间无法释放。 这被称为内存泄漏。
delete[] ch;
您尝试取消分配字符串文字。 这会使您的程序崩溃。 只允许delete
从new
获得的指针和从new[]
获得的delete[]
指针。 删除其他任何内容都有不确定的行为。
第二段:
cout<<"\n "<<ch<<endl;
ch
指向单个字符,而不是以零结尾的char 数组 。 将此指针传递给cout
具有不确定的行为。 您应该使用cout << *ch;
打印该单个字符或确保ch
指向以零结尾的字符数组。
delete[] ch;
您使用new
分配,必须使用delete
取消分配。 在此处使用delete[]
具有未定义的行为。
两者都工作正常。
就像运行时错误一样,“运行良好”是未定义行为的可能结果。
要回答这个问题,两个片段都不正确。 第一个因为您很幸运而崩溃,第二个似乎因为您不幸运而工作了。
解决方案:使用std::string
。
您的程序中有几个错误。
在第一个程序中,您不是删除动态分配的内容,而是删除静态分配的字符串“ hello”。 实际上,当您执行ch =“ hello”时,您并没有在错误分配的缓冲区“ new char”中复制字符串(此new只会分配一个char,而不是您要查找的字符),而是使指针ch指向起点位于不可写内存中某处的字符串“ hello”(通常该字符串直接指向可执行文件)。 因此,删除操作正在尝试取消分配无法取消分配的内容。 因此,第一个程序可以像这样重写:
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;
}
您应该使用类似:
char * ch =新的char [6];
strcpy(ch,“ hello”);
...
delete [] ch;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.