2012-11-29 34 views
2

當我正在運行在調試模式下面的代碼創建的.exe文件,它顯示了一些斷言失敗和程序崩潰但是當我運行從下面的釋放模式創建的相同的exe代碼,其工作正常。程序崩潰而重新分配的字符數組

請幫忙找出爲什麼我歌廳在調試模式下斷言失敗而不是在釋放模式。

#include<iostream> 
using namespace std; 
#include<string.h> 

void main() 
{ 
    char *buf = new char[5]; //pre-allocated buffer 
    buf = "Hello"; 
    delete [] buf; 
    getchar(); 
    //cout<<buf; 
    //string *p = new (buf) string("hi"); //placement new 
    //string *q = new string("hi"); //ordinary heap allocation 
} 
+0

注意,在這種情況下,你可以說'字符BUF [] =「你好」;',你會得到一個副本,你甚至不必取消分配。 – cHao

+0

您很少需要C++中的C字符串,您應該使用''代替。在少數實際需要C頭文件的情況下,您應該使用C++頭文件(例如:)。 – netcoder

回答

4
char *buf = new char[5]; //pre-allocated buffer 

在這裏定義一個指針,並初始化它指向同室5個字符的動態分配的緩衝區。

buf = "Hello"; 

在這裏您初始化指針指向字符串文本的開始。

delete [] buf; 

在這裏,您刪除[] buf中的指針,但BUF指針不再指向你新的[]'卯起來什麼,它指向字符串文字。您只能刪除/刪除[]指向您從new/new []獲得的某個指針。所以,你得到了一個未定義的行爲,並有可能崩潰

你可能意味着你的字符串的內容複製到緩衝區中,你新[]'d。請記住,佔NUL終止:

int main() 
{ 
    char *buf = new char[6]; //pre-allocated buffer 
    strcpy(buf, "Hello"); 
    delete [] buf; 
    getchar(); 
    //cout<<buf; 
    //string *p = new (buf) string("hi"); //placement new 
    //string *q = new string("hi"); //ordinary heap allocation 
} 

雖然,在C++中,你寧願使用std ::從#include <string>串;

std::string = "Hello"; 
+0

感謝您的回覆..我現在得到了這個概念,但是如果程序在發佈模式下運行,它爲什麼不會崩潰。 – Kenta

+0

@viku很難說。當你的代碼做了一些未定義的事情時,幾乎可以發生任何事情。它可能會崩潰,它可能會損壞你的記憶,它可能似乎工作等。 – nos

2

當你這樣做:

buf = "Hello"; 

你基本上改變指針值(內存地址),在此buf指向一個只讀存儲器領域,因爲"Hello"是一個字符串文字,因此存儲在只讀存儲器中。

然後嘗試釋放內存,因此崩潰。

此外,"Hello"爲6字節長,而不是5.

4
  1. void main是錯誤的。 main返回int。沒有例外。
  2. 你在做delete[] "Hello""Hello"是一個字符串文字;你不能delete它。
+0

感謝您的回覆..我現在就理解了這個概念。但是爲什麼程序在發佈模式下運行時不會崩潰 – Kenta

+0

@viku這是未定義的行爲 - 任何事情都可能發生。 –

2
char *buf = new char[6]; //pre-allocated buffer 
strncpy(buf, "hello", 6); 
delete [] buf; 

BUF = 「你好」;會改變buf的值,從一個指向new char [6]的指針指向「hello」,一塊內存不在堆中。

+0

'strncpy'是一個錯誤。 – melpomene

+0

1.當它與字符串無關時,它僞裝成一個字符串函數。來自「簡明英漢詞典」它首先抽象出不應該被抽象的行爲。問題1 + 2導致人們不適當地使用它(因爲沒有適當的使用它)。例如。在上面的代碼中buf [5]最初沒有初始化。 – melpomene

+0

@melpomene:我會稍微同意它不會做任何'memcpy'或'memmove'加上'memset'所不能做的事情。 (最大的差別在於,它將目的地填充到傳入的大小;因此是memset)。然而,在它的防禦中,它的意思是(而且)只是一個更安全的'strcpy'版本。我認爲赤裸角色數組根本不應該被賦予特殊的狀態作爲字符串;一個字符串應該是一個char *'*和*一個長度,或者一個數組應該能夠知道它的大小。 – cHao

2

由於未定義行爲意味着會發生什麼。問題是,buf = "Hello"將字符串文字的地址分配給buf,然後嘗試刪除該文字。在調試模式下編譯時,檢查代碼發現地址不能被刪除;在發佈模式下,檢查沒有完成,並且刪除只是跺腳一些不重要的東西。

2

您試圖取消分配字符串文字"Hello"。這條線:

buf = "Hello"; 

重定向指針buf在字面"Hello"點。你可能打算這樣做:

char *buf = new char[6]; //need one extra space for terminating NUL character 
strcpy(buf, "Hello");