2014-08-29 34 views
-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)

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

有谁请告诉我,为什么第一个与分段故障失败,第二个是工作的罚款既deletedelete[]。因为对我来说这两个程序似乎都是一样的。

+6

这是C++。使用'std :: string'。 'ch'只是一个指针。分配字符串文字只是使其指向字符串文字,并且刚分配的内存将丢失。第二个是未定义的行为,如果你使用'delete []'而不是'delete'。出现工作正常≠工作正常。 – chris 2014-08-29 14:06:28

回答

2

new char产生恰好1个字符(未1个字符的阵列,使用new char[1]为该)

所以删除[]不会在第一示例应用

,则覆写指针到您的分配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; 
} 
+0

但删除也失败..请参阅注释////或删除ch; --->已经试过 – user3990393 2014-08-29 14:06:47

+0

你正在删除静态内存,这就是为什么它是失败的 – BeyelerStudios 2014-08-29 14:08:38

0

您应该使用类似于:

char * ch = new char [6];

strcpy(ch,“hello”);

...

delete [] ch;

+1

只有新的字符[5]不够大,“你好”(6个字符,包括空终止符) – BeyelerStudios 2014-08-29 14:07:16

+0

你是对的我不算好! – Carles 2014-08-29 14:08:01

+0

我也可以使用第二个程序..我的问题是,为什么这是失败..第二个是使用删除和删除[]都... – user3990393 2014-08-29 14:09:13

1

在第一个,你改变指针指向一个字符串:

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'; 
+0

但删除[]也是工作文件没有在第二个程序中失败..那是什么? – user3990393 2014-08-29 14:11:41

+3

好运。或者不是,取决于隐藏的bug何时会突然炸毁。 – Quentin 2014-08-29 14:13:10

+2

@ user3990393:如果您不幸,未定义的行为可能会*显示为“正常工作”。但它可能随时停止工作(如果您更改编译器,或更改代码或无明显原因);你不能依赖它明显的好行为。 – 2014-08-29 14:14:01

1

每个问题都有几个问题,即当您尝试分配字符数组时,您只分配一个字符。

在第一个例子,你还分配单个字符,并随后重新分配指针字符数组 - ch = "hello"复制字符串,只是重新分配的指针。您删除[]的呼叫将尝试删除不是堆分配的字符串,因此会导致seg故障。而且你也泄漏了你分配的字符。

1

这里是什么地方错了两个片段:

第一个片段:

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

这是不合法的分配字符串文本到非const字符指针。 此外,您在拨打new后立即重新分配指针。由new返回的原始值现在永远丢失,并且在程序期间不能自由。这被称为内存泄漏。

delete[] ch; 

您尝试解除分配字符串文字。这会导致程序崩溃。你只能得到delete指针,你从newdelete[]得到的指针可以从new[]得到。删除其他任何内容都有未定义的行为。

第二片段:

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

ch点到单个字符,而不是零封端的炭阵列。将此指针传递给cout具有未定义的行为。您应该使用cout << *ch;来打印该单个字符或确保ch指向零终止的字符数组。

delete[] ch; 

你跟new分配的,必须用delete解除分配。使用delete[]这里有未定义的行为。

两者都工作正常....

“做工精细”是未定义行为的一个可能的结果,就像一个运行时错误。

要回答这个问题,这两个代码段都不正确。第一个因为幸运而崩溃,第二个因为运气不好而出现工作。

解决方法:使用std::string

1

你的程序有几个错误。

在第一个程序中,您并未删除动态分配的内容,而是静态分配的字符串“hello”。事实上,当你执行ch =“hello”时,你并没有在错误分配的缓冲区“new char”中拷贝字符串(这个新的字符只是分配一个字符,而不是你正在寻找的字符),但是你可以让指针指向开始的字符串“hello”位于非可写内存中的某处(通常该字符串直接指向可执行文件)。所以删除操作试图释放一些无法释放的东西。因此,第一个节目culd被改写,如:

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

与大多数其他语言,如果你违背C++,导致内存破坏规则,覆盖缓冲,等等,有没有保证你的程序会崩溃,赛格故障等,让你知道,你做错了什么。

在这种情况下,您幸运的是简单的类型,如char*不受您使用错误形式delete的影响。但是,如果您更改编译器,运行时设置等,则无法保证这将始终有效。