2010-08-07 51 views
1

所以我決定在pesty C++中插入一點。調試斷言錯誤 - 在字符指針上刪除調用

當我調用一個指向我創建的簡單類的指針的刪除函數時,我受到Debug Assertion Failure -Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)的迎接。我認爲這是因爲我處理錯誤的字符串操作,從而導致內存損壞。

我創建了一個基本類,[I] animal [/ I],它具有可以通過函數設置的字符串。

// name 
char * ptrName; 

animal::animal(char * name) 
{ 
this->SetName(name); 
}; 

animal::~animal() 
{ 
delete [] ptrName; 
} 

void animal::SetName(char * name) 
{ 
ptrName = name; 
}; 

當使用上面的類如下所示時,會發生錯誤。我試過delete ptrNamedelete [] ptrName,但無濟於事。

animal * cat = new animal("Optimus Prime"); 
delete cat; 

我錯過了什麼?

回答

1

所以我決定在pesty C++中插入一點。

然後自己動手,用C++ right。這是使用std::string

// name 
std::string name_; 

animal::animal(const std::string& name) 
    : name_(name) 
{ 
} 

//animal::~animal() // not needed any longer 

//note: copying also automatically taken care of by std::string 
//animal(const animal&) 
//animal& operator=(const animal&) 

void animal::SetName(const std::string& name) 
{ 
name_ = name; 
} 

看一看The Definitive C++ Book Guide and List。我推薦加速C++。它帶有一個陡峭的學習曲線,但由於您已經瞭解了一些C++,因此這250頁可能會讓您處於正確的軌道。

作爲一個經驗法則:當你釋放資源(內存或其他),它不是的一類,其僅目的是管理這一資源的析構函數,什麼是錯的與您的設計。就我個人而言,每當我覺得需要編寫析構函數,複製構造函數或賦值運算符時,我都會變得可疑。

+0

我剛剛從Amazon訂購了Accelerated C++。當您將name_變量設置爲新值時,不需要取消分配name_變量的原因是什麼? – 2010-08-07 18:23:10

+0

所有的分配和釋放邏輯都隱藏在std :: string的後面。 – 2010-08-07 18:38:01

+0

@Qua:當它是'std :: string'時,那麼這個類會爲你處理內存管理。當它是C字符串(指向動態分配數組的第一個字符的指針)時,必須手動完成。但是,你還必須跟蹤哪個指針真的指向一個動態分配的數組。字符串文字不是動態分配的,所以它不需要'delete []''d。但是在你的類的內部,你不知道指針是否指向動態分配的數組。所以你必須總是把它複製到你自己的數組中,然後離開... – sbi 2010-08-07 18:43:08

1

誰擁有你的字符串?

例如,當你構建你的新動物時,你正在傳遞一個字符串 - 這不是你的自由。

你應該考慮避免char *而只是使用std :: string來代替。

如果您必須使用char *,請考慮所有權。例如,一個選項是讓你獲取字符串的副本(使用strdup)並擁有它。你可以用奇怪的蟲子被卡住不能這樣

char* szFoo = strdup("my string"); 
{ 
    animal a(szFoo); 
} 
// At this point szFoo has been deleted by the destructor of a 
// and bad things will start to happen here. 
printf("The value of my string %s",szFoo); 
2

字符串"Optimus Prime"這種方式不是動態分配的,因此它是不正確的調用delete就可以了。

2

問題來自刪除您不擁有的指針。你還沒有分配字符串,所以你不能刪除它。您正在使用的C字符串由編譯器靜態分配。

2

問題是,在setName函數中,您只是將名稱分配給ptrName。在這個例子中,這個名字是一個你不能刪除的const char字符串指針(它不是在堆上分配的)。爲了避免這個錯誤,你可以在類中使用std :: string,或者在animal類的構造函數中分配一個新的字符並將指針指向它。然後,在析構函數中,您可以刪除該數組。