2010-12-11 78 views
7

只是爲了測試我已經創建了下面的代碼:段故障

#include<stdio.h> 

int main(){ 
    char *p = "Hello world"; 
    *(p+1) = 'l'; 
    printf("%s", p); 
    return 0; 
} 

但是,當我在ubuntu下10.04跑這在我的「GCC」編譯我:

Segmentation fault 

所以誰能解釋爲什麼會發生這種情況。

#include<stdio.h> 
#include<stdlib.h> 

int main(){ 
    char *p = malloc(sizeof(char)*100); 
    p = "Hello world"; 
    *(p+1) = 'l'; 
    printf("%s", p); 
    free(p); 
    return 0; 
} 

這也導致段錯誤 由於提前

+0

可能重複接收到分段錯誤?](http://stackoverflow.com/questions/164194/why-does-simple-c-code-receive-segmentation-fault) – Joe 2010-12-11 12:38:48

+4

...以及過去幾年中大約二十個其他SO問題。 – Joe 2010-12-11 12:39:06

回答

6

char *p = "Hello world"; *(p+1) = 'l';

Modiying一個字符串字面的(即的 「Hello World」 在你的代碼)的含量爲未定義行爲。

ISO C99(第6.4.5節/ 6)

它是unspeci音響ED這些陣列是否是不同的條件是它們的元素具有適當的值。 如果程序試圖修改這樣一個數組,行爲是undefined

嘗試使用字符數組。

char p[] = "Hello World"; 
p[1] = 'l'; 

編輯

你修改後的代碼

#include<stdio.h> 
#include<stdlib.h> 
int main() 
{ 
    char *p = malloc(sizeof(char)*100); 
    p = "Hello world"; // p now points to the string literal, access to the dynamically allocated memory is lost. 
    *(p+1) = 'l'; // UB as said before edits 
    printf("%s", p); 
    free(p); //disaster 
    return 0; 
} 

調用未定義行爲,以及因爲你尚未使用malloc分配試圖解除分配的內存(使用free)的部分

+0

嘿,請檢查修改後的問題 – codeomnitrix 2010-12-11 12:41:14

+0

...並且因爲只讀內存仍在修改中,因爲'p =「Hello world」'p不再指向'malloc'ed內存。 – Vlad 2010-12-11 12:45:47

+0

好吧,那是否意味着以前分配的內存(通過malloc)丟失,現在我正在使用的是由編譯器爲字符串文字「Hello world」分配的內存的新內存部分。我對嗎? – codeomnitrix 2010-12-11 12:46:54

2

因爲char *p = "Hello world"幾乎肯定給你一個指針,只讀存儲器,這意味着,試圖與*(p+1) = 'l'改變它是一個明確的NO-否(即使內存不是隻讀的,行爲仍未定義)。

C99參照字符串文字的相關部分是在6.4.5 para 6

它是未指定的這些陣列是否是不同的條件是它們的元件具有 適當的值。如果程序試圖修改這樣一個數組,行爲是 未定義。


你之所以仍然得到一個分段錯誤的東西,如:

char *p = malloc (100); // sizeof(char) is ALWAYS 1 
p = "Hello";    // better would be: strcpy (p, "Hello") 
*p = 'a'; 

是因爲,即使你分配你要允許修改內存,第二條語句將指針更改爲指向字符串文字(因爲您無法訪問分配的內存,因此會導致內存泄漏),因此不允許修改。

您需要區分指針對指針指向所做更改的更改。

+0

但是當我寫p =「嗨」。它沒有問題。 – codeomnitrix 2010-12-11 12:38:11

+0

這是因爲您正在將指針更改爲指向另一個字符串文字,而不是嘗試更改字符串文字本身。 – paxdiablo 2010-12-11 12:40:10

+0

好的,但如果內存是通過malloc分配的話。正如我在我的問題的新代碼部分所做的一樣。 – codeomnitrix 2010-12-11 12:44:17

1

"Hello world"是一個字符串文字。它由內存區域中的一大塊字節表示,其中可能不會被修改char *p指向那個字節塊。 *(p+1) = 'l'表示覆蓋下一個字節後指向一個'l'。指針之後的下一個字節是可能未被修改的塊的一部分。試圖重寫某些內容正試圖修改它。嘗試修改不允許修改的內容非常糟糕。

爲了在存儲器中具有其文本可以被修改的副本,把它放到一個數組,例如char p[] = "Hello world";。 (請注意,聲明數組這樣使得正是大到足以容納字符串,因此,你可能不會延長它,因爲沒有更多的空間。)的[爲什麼簡單的C代碼