简体   繁体   English

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

[英]Segmentation Fault in deleting char pointer

I'm posting two fragments here. 我在这里发布两个片段。 The first one is giving me Segmentation Fault on deallocating the memory. 第一个是在分配内存时给我Segmentation Fault。 Second one is working fine. 第二个工作正常。

1) 1)

int main()
{
  char* ch = new char;
  ch = "hello";
  cout << "\n " << ch << endl;
  delete[] ch;  ////OR delete ch; ---> have tried both
  return 0;
}

2) 2)

int main()
{
  char* ch = new char;
  cin >> ch;
  cout << "\n " << ch << endl;
  delete[] ch;   ///OR delete ch /// Both are working fine....
  return 0;
}

Could anybody please tell me why the first one is failing with Segmentation Fault and second one is working fine with both delete and delete[] . 谁能告诉我为什么第一个失败并出现Segmentation Fault而第二个失败时使用deletedelete[] Because to me both the program seems to same. 因为对我来说,这两个程序似乎相同。

new char generates exactly 1 character (not an array of 1 character, use new char[1] for that) new char生成正好1个字符(不是1个字符的数组,请使用new char[1]

so delete[] doesn't apply 因此delete []不适用

in the first example, you overwrite your pointer to your allocated 1 character with a pointer to the character string "hello" - deleting this string (as it is static memory) will result in sesgfault 在第一个示例中,您使用指向字符串“ hello”的指针覆盖了指向已分配的1个字符的指针-删除此字符串(因为它是静态内存)将导致sesgfault

Edit 编辑

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

There are issues with both examples: 这两个示例都存在问题:

  char* ch = new char;`
  ch = "hello";`    

The new returns an address that points to dynamically allocated memory. new函数返回一个指向动态分配内存的地址。 You must save this return value so that delete can be issued later. 您必须保存此返回值,以便以后可以发布delete The code above overwrites this value with "hello" (a string-literal). 上面的代码用“ hello”(字符串字面量)覆盖此值。 You now have lost the value, and thus can not call delete with the proper value. 您现在已经丢失了该值,因此无法使用适当的值调用delete

The second example, even though you say "works fine" is still faulty. 第二个示例,即使您说“工作正常”仍然是错误的。

  char* ch = new char;`    
  delete[] ch;   ///OR delete ch /// Both are working fine....`    

The wrong form of delete is used. 使用了错误的delete形式。 You allocated with new , so you must deallocate with delete , not delete[] . 您分配了new ,因此必须使用delete而不是delete[]取消分配。 It works this way: new -> delete , new[] -> delete[] . 它是这样工作的: new > deletenew[] -> delete[]

Unlike most other languages, if you go against the rules of C++, corrupt memory, overwrite a buffer, etc., there is no guarantee that your program will crash, seg fault, etc. to let you know that you've done something wrong. 与大多数其他语言不同,如果您违反C ++规则,损坏的内存,覆盖缓冲区等,则无法保证程序会崩溃,出现段错误等,以使您知道自己做错了什么。

In this case, you're lucky that simple types such as char* are not affected by you using the wrong form of delete . 在这种情况下,您很幸运,使用错误形式的delete不会影响诸如char*类的简单类型。 But you cannot guarantee that this will always work if you change compilers, runtime settings, etc. 但是您不能保证如果您更改编译器,运行时设置等,它将始终有效。

In the first one, you change the pointer to point to a string literal: 在第一个中,您将指针更改为指向字符串文字:

ch = "hello";

String literals are static arrays, so mustn't be deleted. 字符串文字是静态数组,因此不能删除。

The second is wrong for at least two reasons: 第二个错误至少有两个原因:

  • you allocate a single character, not an array; 您分配一个字符,而不是数组; a single character would be deleted with delete not delete[] 单个字符将被删除,而delete不是delete[]
  • cin>>ch will (most likely) read more than one character, but you've only allocated space for one. cin>>ch将(很可能)读取多个字符,但是您仅为一个字符分配了空间。

Both of these cause undefined behaviour, which might manifest itself as a visible error, or might appear to "work fine" - but could fail when you least expect it. 这两种情况都会导致不确定的行为,这可能会表现为可见错误,或者看起来似乎“工作正常”,但在您最不期望的情况下可能会失败。

To allocate an array, use new char[SIZE] ; 要分配数组,请使用new char[SIZE] ; but even then, you can't prevent the user from giving too much input and overflowing the buffer. 但是即使如此,您仍不能阻止用户提供过多的输入并溢出缓冲区。

Unless you're teaching yourself how to juggle raw memory (which is a dark art, best avoided unless absolutely necessary), you should stick to high-level types that manage memory for you: 除非您正在教自己如何处理原始内存(这是一门黑手艺,除非绝对必要,否则最好避免这样做),否则您应该坚持为您管理内存的高级类型:

std::string string;
string = "hello";
std::cout << string << '\n';
std::cin >> string;
std::cout << string << '\n';

There are a couple of problems with each, namely that you're only allocating a single character when you're trying to allocate a character array. 每种方法都有两个问题,即尝试分配字符数组时仅分配一个字符。

In the first example, you're also allocating a single character and then subsequently reassign the pointer to a character array - ch = "hello" will not copy the string, just reassign the pointer. 在第一个示例中,您还分配了一个字符,然后将指针重新分配给字符数组ch = "hello" 不会复制字符串,只是重新分配指针。 Your call to delete[] will then attempt to delete a string that is not heap allocated, hence the seg fault. 然后,您对delete []的调用将尝试删除未分配堆的字符串,因此出现段错误。 And you're also leaking the char you allocated, too. 而且,您还会泄漏您分配的字符。

Here's what's wrong with both snippets: 这两个片段都出了什么问题:

First snippet: 第一个片段:

char* ch = new char; ch = "hello";

It's not legal to assign a string literal to a non-const char pointer . 将字符串常量分配给非const char指针是不合法的。 Also, you re-assign the pointer immediately after you call new . 另外,您在调用new之后立即重新分配指针。 The original value returned by new is now lost forever and can not be free for the duration of the program. 现在, new返回的原始值将永远丢失,并且在程序执行期间无法释放。 This is known as a memory leak. 这被称为内存泄漏。

delete[] ch;

You try to deallocate the string literal. 您尝试取消分配字符串文字。 This crashes your program. 这会使您的程序崩溃。 You are only allowed to delete pointers that you get from new and delete[] pointers that you get from new[] . 只允许deletenew获得的指针和从new[]获得的delete[]指针。 Deleting anything else has undefined behaviour. 删除其他任何内容都有不确定的行为。

Second snippet: 第二段:

cout<<"\n "<<ch<<endl;

ch points to a single character, not a zero terminated char array . ch指向单个字符,而不是以零结尾的char 数组 Passing this pointer to cout has undefined behaviour. 将此指针传递给cout具有不确定的行为。 You should use cout << *ch; 您应该使用cout << *ch; to print that single character or make sure that ch points to a character array that is zero terminated. 打印该单个字符或确保ch指向以零结尾的字符数组。

delete[] ch;

You allocated with new , you must deallocate with delete . 您使用new分配,必须使用delete取消分配。 Using delete[] here has undefined behaviour. 在此处使用delete[]具有未定义的行为。

Both are working fine.... 两者都工作正常。

"working fine" is one possible outcome of undefined behaviour, just like a runtime error is. 就像运行时错误一样,“运行良好”是未定义行为的可能结果。

To answer the question, neither snippet is correct. 要回答这个问题,两个片段都不正确。 First one crashes because you got lucky, second one appears to work because you got unlucky. 第一个因为您很幸运而崩溃,第二个似乎因为您不幸运而工作了。

Solution: Use std::string . 解决方案:使用std::string

there are several errors in your programs. 您的程序中有几个错误。

In the first program you are not deleting something dynamically allocated but the statically allocated string "hello". 在第一个程序中,您不是删除动态分配的内容,而是删除静态分配的字符串“ hello”。 Infact when you execute ch="hello" you are not copying the string in the wrongly allocated buffer "new char" ( this new just allocates one char, not what you are looking for ) but you makes the pointer ch to point to the start of the string "hello" located somewhere in the non writable memory ( normaly that string are pointed directly into the executable ). 实际上,当您执行ch =“ hello”时,您并没有在错误分配的缓冲区“ new char”中复制字符串(此new只会分配一个char,而不是您要查找的字符),而是使指针ch指向起点位于不可写内存中某处的字符串“ hello”(通常该字符串直接指向可执行文件)。 So the delete operation is trying to deallocate something that cannot be deallocate. 因此,删除操作正在尝试取消分配无法取消分配的内容。 So the first program culd be rewritten like: 因此,第一个程序可以像这样重写:

int main()
{
  const char* ch = "hello";
  cout<<"\n "<<ch<<endl;
  return 0;
}

or like 或喜欢

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

You should use something like: 您应该使用类似:

char* ch = new char[6] ; char * ch =新的char [6];

strcpy(ch,"hello") ; strcpy(ch,“ hello”);

... ...

delete[] ch ; delete [] ch;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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