删除字符指针时出现分段错误

时间:2014-08-29 14:02:18

标签: c++ pointers

我在这里张贴了两个片段。 第一个是在释放内存时给我分段错误。第二个工作正常。

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;
}

有人可以告诉我为什么第一个失败的分段错误,第二个与deletedelete[]一起正常工作。因为对我而言,这两个程序看起来都是一样的。

7 个答案:

答案 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; deletenew[] - &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获得的newdelete[]指针获得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;