2010-06-20 135 views
4
int main() 
{ 
    char *name = new char[7]; 
    name = "Dolphin"; 
    cout << "Your name is : " << name <<endl; 
    delete [] name; 
} 

爲什麼VC++編譯器不會抱怨?這段代碼有什麼問題?

+10

你應該使用'std :: string',它允許這樣的事情。 – GManNickG 2010-06-20 17:15:34

+4

它並不抱怨,因爲C/C++程序員被假定知道他們在做什麼。指向其他地方的「名字」是完全合法的。雖然在這種情況下,我希望GCC發出警告,因爲您使用(char *)指針訪問常量部分。我不知道VC++ 另外,如果你什麼都不說,main()返回0. – Phil 2010-06-20 17:41:12

+1

爲什麼它應該抱怨?就編譯器而言,你沒有做任何違法的事情。編譯器不是心靈感應,你知道,他們不知道你想做什麼,而不是你實際做了什麼。 – AnT 2010-06-20 18:13:09

回答

14

你有兩個問題在這裏:

首先,這有什麼錯碼?那麼......

當你指定「海豚」來命名你沒有複製到分配的數組中時,你正在調整指針指向字符串文字。稍後嘗試刪除指針指向的內容。我希望這會在某些環境中崩潰。

如果您確實需要「海豚」字符的副本,請查看strncpy(),但是如您已經觀察到的那樣,您還需要空值。

其次,爲什麼特定的編譯器不會警告您該作業是潛在的:這有點困難。 [已經觀察到其他編譯器會發出警告。]問題是,這個編譯器是否將字符串文字視爲「指向const char的指針」或「指向char的指針」。

如果是前者的情況,那麼我會期待一個錯誤。直到2004年左右,C++在將文字作爲char指針處理時與C保持一致,因此賦值是允許的。所以我想你的問題是確定你正在使用的規範的版本,這可能取決於你使用的VC++版本以及你選擇的編譯器選項。

MSDN C++ reference表示VC++將字符串文字視爲非常量。我會留給VC++大師進一步評論。

+3

加上原始內存泄漏。加上其他人所說的陣列是一個字符太小。雖然關於數組大小的部分有點不對,因爲你根本沒有把Dolphin放進去。你只是在泄漏記憶。 – 2010-06-20 17:13:26

+0

你的回答是完全正確的,但我再次看到他的問題,它是「爲什麼不是VC++編譯器抱怨」 – Phil 2010-06-20 17:36:51

+1

問題是爲什麼編譯器不會抱怨。 – Cam 2010-06-20 17:49:54

0

C風格的字符串必須爲空(「Dolphin \ 0」)。編譯器會爲你做這件事,但你沒有給它足夠的空間。將其更改爲:

char *name = new char[8]; 
+0

不,這裏沒有任何意義。變量「名稱」正在重新分配,所以初始分配無關緊要。 – Pointy 2010-06-20 17:12:58

2
  1. 您需要分配8個字符
  2. 您不能分配一個字符串這樣。使用const char *name = "Dolphin"(不需要分配!)並且不要刪除或使用strcpy將文本複製到新分配的空間 - 稍後刪除。

您不能刪除駐留在只讀存儲器中的字符串文字(「Dolphin」)。同樣在該筆記上 - 當您編寫name = "Dolphin"時,您將重新分配指針,這意味着最初分配的內存會丟失。

10

這行不好:

name = "Dolphin"; 

那不是複製一個字符串,但重新分配的指針。

所以這會導致兩個問題。

  1. 您在這裏釋放非分配的內存delete [] name;因爲你試圖釋放的指針文字串「海豚」
  2. 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; 
} 
+2

我想你想從'strdup_via_new'而不是'str'返回'tmp' – 2010-06-20 17:29:03

+0

@MichaelTrybus - 是的,我的意思是返回'tmp'。謝謝你打電話給我。 – 2010-06-21 01:55:48

3

的問題是,你正在嘗試delete一個字符串常量,「海豚」。

0

作業是否具體使用new和delete來證明你知道如何?在這種情況下,您需要爲空終止符節省空間並使用strcpy。如果沒有,也許你應該演示初始化?

1
  1. 您還沒有iostream,並表示你,而你正在使用cout和CIN,其中定義是using namespace std;
  2. 你有行內存泄漏4. name指出了一些記憶,如果你分配一個字符串文字,你實際上正在分配一個指向它的指針,從而失去了指向先前分配的7個字節的指針,
  3. 在第6行中,你試圖釋放一塊內存,這大概是在只讀存儲器,因爲它是由編譯器從字符串文字準備的。標準不允許你釋放這些內存。這樣做將是

兩個正確的方法:

#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。編譯器也不會抱怨刪除字符串文字的內存,因爲它不會分析你對指針做了什麼,因爲你已經爲它指定了一個字符串文字的地址,所以它不知道它沒有改變自那以後。

+0

在第二個列表中,您應該包含''。 – 2010-06-20 19:22:00

+0

謝謝,更正。 – 2010-06-21 06:22:44

1
const char* name; 

就足夠了。當您將「Dolphin」分配給名稱時,指針的值會更改。 最後,delete[] name是錯誤的。它試圖刪除不在堆上分配的常量char *「Dolphin」。

所以,整個代碼可以讀取

int main() 
{ 
    const char *name; 
    name = "Dolphin"; 
    cout << "Your name is : " << name <<endl; 
} 

編譯器不會抱怨,因爲你的代碼並沒有違反C++的語法

+1

'char * name'是不夠的。它應該是'const char * name'。 – laura 2010-06-20 17:21:35

+0

@laura:儘管如此,'char *'是允許的。它只是被棄用。 – GManNickG 2010-06-20 17:23:31

+0

勞拉,感謝您的輸入,你說的最好是使用'const char *'。我相應地改變了答案。 – 2010-06-20 17:25:04

1

此問題,此代碼開始行:

name = "Dolphin"; 

這很好,因爲它將變量名賦給字符串常量「Dolphin」,但是行:

delete [] name; 

試圖刪除未定義的字符串常量。

你應該使用類似std :: string來處理你的字符串。

VC++沒有抱怨,因爲它是C++,語言期望你知道你在做什麼。 「C可以很容易地將自己踢在腳上,C++使它更難,但是當你這樣做時,它會吹走你的整條腿。」 - Bjarne Stroustrup

0

可能是因爲VC++認爲,這就是你想要在程序中做的。幾乎沒有任何語法錯誤。所以它確定。可能鏈接器調用內存泄漏錯誤?

這些天做編譯器檢查邏輯嗎?

0

此源代碼例舉了不合格程序與具有邏輯錯誤(導致程序錯誤操作的錯誤)的程序之間的區別。 C++編譯器只需要「抱怨」一個格式不正確的程序,而這個源代碼不是。

在此程序中的邏輯錯誤包括:

  1. 引起線name = "Dolphin"
  2. 嘗試調用delete[]上不是由new[]

返回另外一個指針內存泄漏,儘管您沒有將"Dolphin"複製到7字符數組中,但似乎您打算這樣做。你必須要小心的是,目的地分配先後爲字符組成的字符串空間"Dolphin"'D''o''l''p''h''i''n''\0')。

0

代碼有什麼問題? A.它有內存泄漏。 B.它做不必要的新

char *name = new char[7]; 

是不是必要的,因爲你最終將分配名稱靜態分配的字符串

name = "Dolphin"; 

C.即使它實際上做了什麼,它的目的是做..應該是char [8]而不是char [7]。這是邀請seg故障

爲什麼不VC++編譯器抱怨?編譯器並不是真的打算抱怨內存泄漏和邏輯錯誤。

HTH