繁体   English   中英

删除char指针时出现分段错误

[英]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而第二个失败时使用deletedelete[] 因为对我来说,这两个程序似乎相同。

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 > deletenew[] -> 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;

您尝试取消分配字符串文字。 这会使您的程序崩溃。 只允许deletenew获得的指针和从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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM