int main()
{
char *name = new char[7];
name = "Dolphin";
cout << "Your name is : " << name <<endl;
delete [] name;
}
爲什麼VC++編譯器不會抱怨?這段代碼有什麼問題?
int main()
{
char *name = new char[7];
name = "Dolphin";
cout << "Your name is : " << name <<endl;
delete [] name;
}
爲什麼VC++編譯器不會抱怨?這段代碼有什麼問題?
你有兩個問題在這裏:
首先,這有什麼錯碼?那麼......
當你指定「海豚」來命名你沒有複製到分配的數組中時,你正在調整指針指向字符串文字。稍後嘗試刪除指針指向的內容。我希望這會在某些環境中崩潰。
如果您確實需要「海豚」字符的副本,請查看strncpy(),但是如您已經觀察到的那樣,您還需要空值。
其次,爲什麼特定的編譯器不會警告您該作業是潛在的:這有點困難。 [已經觀察到其他編譯器會發出警告。]問題是,這個編譯器是否將字符串文字視爲「指向const char的指針」或「指向char的指針」。
如果是前者的情況,那麼我會期待一個錯誤。直到2004年左右,C++在將文字作爲char指針處理時與C保持一致,因此賦值是允許的。所以我想你的問題是確定你正在使用的規範的版本,這可能取決於你使用的VC++版本以及你選擇的編譯器選項。
MSDN C++ reference表示VC++將字符串文字視爲非常量。我會留給VC++大師進一步評論。
C風格的字符串必須爲空(「Dolphin \ 0」)。編譯器會爲你做這件事,但你沒有給它足夠的空間。將其更改爲:
char *name = new char[8];
不,這裏沒有任何意義。變量「名稱」正在重新分配,所以初始分配無關緊要。 – Pointy 2010-06-20 17:12:58
const char *name = "Dolphin"
(不需要分配!)並且不要刪除或使用strcpy
將文本複製到新分配的空間 - 稍後刪除。您不能刪除駐留在只讀存儲器中的字符串文字(「Dolphin」)。同樣在該筆記上 - 當您編寫name = "Dolphin"
時,您將重新分配指針,這意味着最初分配的內存會丟失。
這行不好:
name = "Dolphin";
那不是複製一個字符串,但重新分配的指針。
所以這會導致兩個問題。
delete [] name;
因爲你試圖釋放的指針文字串「海豚」char *name = new char[7];
分配的內存泄漏。由於這是C++,您應該只使用std::string
。無需手動分配或釋放,然後你會得到價值語義:
int main()
{
std::string name;
name = "Dolphin";
cout << "Your name is : " << name <<endl;
}
最後,如果你想了解原始指針好,這裏是你的代碼的一個版本,將正常工作。需要注意的重要的事情是,代碼分配的長度+ 1(額外+1是終止NUL字節),並使用的strcpy將數據複製到新分配的內存:
char *strdup_via_new(const char *str)
{
char *tmp = new char[strlen(str) + 1];
strcpy(tmp, str);
return tmp;
}
int main()
{
char *name = strdup_via_new("Dolphin");
cout << "Your name is : " << name <<endl;
delete [] name;
}
我想你想從'strdup_via_new'而不是'str'返回'tmp' – 2010-06-20 17:29:03
@MichaelTrybus - 是的,我的意思是返回'tmp'。謝謝你打電話給我。 – 2010-06-21 01:55:48
的問題是,你正在嘗試delete
一個字符串常量,「海豚」。
作業是否具體使用new和delete來證明你知道如何?在這種情況下,您需要爲空終止符節省空間並使用strcpy
。如果沒有,也許你應該演示初始化?
iostream
,並表示你,而你正在使用cout和CIN,其中定義是using namespace std;
,name
指出了一些記憶,如果你分配一個字符串文字,你實際上正在分配一個指向它的指針,從而失去了指向先前分配的7個字節的指針,兩個正確的方法:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char *name = new char[8];
strcpy(name, "Dolphin");
cout << "Your name is : " << name <<endl;
delete [] name;
return 0;
}
這裏要注意,對存儲「海豚」你需要8個字節,1無二NULL字符。 第二個版本(更多C++):
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name = "Dolphin";
cout << "Your name is : " << name <<endl;
return 0;
}
而這一次不需要任何刪除。
編譯器沒有抱怨的原因很簡單,編譯器不會檢查你的內存泄漏。還有其他程序可以做到這一點,例如valgrind。編譯器也不會抱怨刪除字符串文字的內存,因爲它不會分析你對指針做了什麼,因爲你已經爲它指定了一個字符串文字的地址,所以它不知道它沒有改變自那以後。
在第二個列表中,您應該包含'
謝謝,更正。 – 2010-06-21 06:22:44
const char* name;
就足夠了。當您將「Dolphin」分配給名稱時,指針的值會更改。 最後,delete[] name
是錯誤的。它試圖刪除不在堆上分配的常量char *「Dolphin」。
所以,整個代碼可以讀取
int main()
{
const char *name;
name = "Dolphin";
cout << "Your name is : " << name <<endl;
}
編譯器不會抱怨,因爲你的代碼並沒有違反C++的語法
此問題,此代碼開始行:
name = "Dolphin";
這很好,因爲它將變量名賦給字符串常量「Dolphin」,但是行:
delete [] name;
試圖刪除未定義的字符串常量。
你應該使用類似std :: string來處理你的字符串。
VC++沒有抱怨,因爲它是C++,語言期望你知道你在做什麼。 「C可以很容易地將自己踢在腳上,C++使它更難,但是當你這樣做時,它會吹走你的整條腿。」 - Bjarne Stroustrup
可能是因爲VC++認爲,這就是你想要在程序中做的。幾乎沒有任何語法錯誤。所以它確定。可能鏈接器調用內存泄漏錯誤?
這些天做編譯器檢查邏輯嗎?
此源代碼例舉了不合格程序與具有邏輯錯誤(導致程序錯誤操作的錯誤)的程序之間的區別。 C++編譯器只需要「抱怨」一個格式不正確的程序,而這個源代碼不是。
在此程序中的邏輯錯誤包括:
name = "Dolphin"
delete[]
上不是由new[]
返回另外一個指針內存泄漏,儘管您沒有將"Dolphin"
複製到7字符數組中,但似乎您打算這樣做。你必須要小心的是,目的地分配先後爲字符組成的字符串空間"Dolphin"
('D'
,'o'
,'l'
,'p'
,'h'
,'i'
,'n'
和'\0'
)。
代碼有什麼問題? A.它有內存泄漏。 B.它做不必要的新
char *name = new char[7];
是不是必要的,因爲你最終將分配名稱靜態分配的字符串
name = "Dolphin";
C.即使它實際上做了什麼,它的目的是做..應該是char [8]而不是char [7]。這是邀請seg故障
爲什麼不VC++編譯器抱怨?編譯器並不是真的打算抱怨內存泄漏和邏輯錯誤。
HTH
你應該使用'std :: string',它允許這樣的事情。 – GManNickG 2010-06-20 17:15:34
它並不抱怨,因爲C/C++程序員被假定知道他們在做什麼。指向其他地方的「名字」是完全合法的。雖然在這種情況下,我希望GCC發出警告,因爲您使用(char *)指針訪問常量部分。我不知道VC++ 另外,如果你什麼都不說,main()返回0. – Phil 2010-06-20 17:41:12
爲什麼它應該抱怨?就編譯器而言,你沒有做任何違法的事情。編譯器不是心靈感應,你知道,他們不知道你想做什麼,而不是你實際做了什麼。 – AnT 2010-06-20 18:13:09