2016-11-30 51 views
-5

我想了解指針和我有這個簡單的例子c char字符數組,指針,malloc的,免費

void third(char ****msg) { 
    ***msg = malloc(5 * sizeof (char)); 
    printf("\nthe msg in third is :%s ", ***msg); 
    strcpy(***msg, "third"); 
    printf("\nthe msg in third after is: %s", ***msg); 
    // free(***msg); 
} 

void change(char***msg) { 
    **msg = malloc(5 * sizeof (char)); 
    printf("\nthe msg in change is :%s ", **msg); 
    strcpy(**msg, "change"); 
    printf("\nthe msg in change after is: %s", **msg); 
    third(&msg); 
    // free(**msg); 
} 

void test(char ** msg) { 
    *msg = malloc(5 * sizeof (char)); 
    printf("\n the msg in test is: %s", *msg); 

    strcpy(*msg, "test"); 
    printf("\nthe msg in test after is: %s\n", *msg); 

    change(&msg); 
    free(*msg); 
} 

int main(int argc, char** argv) { 

    char * msg; 
    test(&msg); 
    printf("\nthe msg back in main is: %s", msg); 
} 

我可以說,這是工作正常,但你能告訴我什麼時候以及如何我需要釋放分配的內存,因爲如果我從函數中刪除//更改,並運行它,我有錯誤。 ,是有辦法讓每個函數的第一個print語句的消息的內容 - 看到otuput:

the msg in test is: 
the msg in test after is: test 
the msg in change is :0�� 
the msg in change after is: change 
the msg in third is :P�� 
the msg in third after is: third 
the msg back in main is: 

有沒有辦法讓在變化中味精是:測試,然後 味精第三個是:更改

+0

你「擁有」什麼「錯誤」? –

+7

簡單的例子?有四個開始?你已經遠遠超過了成爲一名高級程序員。 –

+2

哇!你是我看到的第一個C程序員!你知道作爲一個三星級的C程序員已經不是恭維了,對嗎? – Olaf

回答

2

忘掉那個節目,還有它只是太多的錯誤:

  • 你不需要間接的多個級別。兩個級別就夠了。如果該函數需要更改地址,只需傳遞指向下一個函數的指針即可。
  • 您嘗試在初始化之前打印字符串。
  • 您嘗試釋放它後使用該字符串。
  • 您通過反覆調用malloc而不清理舊內容來創建內存泄漏。改用realloc。
  • 您分配的內存量不正確,所以數組不夠大,無法保存strcpy中的字符串。另請注意,您需要爲空終止符分配足夠的空間。

依此類推。這裏有一個固定版本:

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

void third(char** msg) { 
    const char str[] = "third"; 

    *msg = realloc(*msg, sizeof(str)); 
    printf("the msg in third is :%s\n", *msg); 

    strcpy(*msg, str); 
    printf("the msg in third after is: %s\n", *msg); 
} 

void change(char** msg) { 
    const char str[] = "change"; 

    *msg = realloc(*msg, sizeof(str)); 
    printf("the msg in change is :%s\n", *msg); 

    strcpy(*msg, str); 
    printf("the msg in change after is: %s\n", *msg); 

    third(msg); 
} 

void test(char** msg) { 
    const char str[] = "test"; 

    *msg = malloc(sizeof(str)); 
    printf("the msg in test is just garabage at this point, no need to print it.\n"); 

    strcpy(*msg, str); 
    printf("the msg in test after is: %s\n", *msg); 

    change(msg); 
} 

int main(int argc, char** argv) { 

    char* msg; 
    test(&msg); 
    printf("the msg back in main is: %s\n", msg); 

    free(msg); 
} 
+0

非常好!現在我明白了,這是否適用於其他數據類型,例如int或int []? –

+0

@JohnRichards數組的數據類型並不重要,但用作字符串的char數組是個特例,因爲當聲明'const char str [] =「test」;''你得到一個由4個字符組成的數組+ 1個空終止符,這就是'sizeof(str)'起作用的原因。 – Lundin

1

在現實生活中,避免使用盡可能多的「明星」(即間接數)。此外,您的代碼中有幾個問題涉及undefined behavior (UB)

void third(char ****msg) { 
    ***msg = malloc(5 * sizeof (char)); 
    printf("\nthe msg in third is :%s ", ***msg);// Don't do that, ***msg is not intialize => UB 
    strcpy(***msg, "third"); // Don't do that => ***msg has 5 bytes, and you copy 6 char => UB 
    printf("\nthe msg in third after is: %s", ***msg); 
    // free(***msg); 
} 

void change(char***msg) { 
    **msg = malloc(5 * sizeof (char)); 
    printf("\nthe msg in change is :%s ", **msg);// Don't do that, **msg is not intialize => UB 
    strcpy(**msg, "change"); // Don't do that => **msg has 5 bytes, and you copy 7 char => UB 
    printf("\nthe msg in change after is: %s", **msg); 
    third(&msg); 
    // free(**msg); 
} 

void test(char ** msg) { 
    *msg = malloc(5 * sizeof (char)); 
    printf("\n the msg in test is: %s", *msg); // Don't do that, *msg is not intialize => UB 

    strcpy(*msg, "test"); 
    printf("\nthe msg in test after is: %s\n", *msg); 

    change(&msg); 
    free(*msg); 
} 

int main(int argc, char** argv) { 

    char * msg; 
    test(&msg); 
    printf("\nthe msg back in main is: %s", msg); //UB => you use freed variable 
} 

修正UB的這種多源之後,它仍然一個不好的設計:使用free功能

的根據是,您使用的指針的指針...當你在一個函數裏面做了一個malloc,你還修改了調用者的指針。試運行這個看看:

void first(char **t) 
{ 
    *t = malloc(5*sizeof(char)); 
} 

int main(int argc, char * argv[]) 
{ 
    char * t = NULL; 
    printf("%p\n", t); 
    first(&t); 
    printf("%p\n", t); 
    return 0; 
} 

它產生(demo):所以,當你自由test,你可用內存分配third


最後

(nil) 
0x995f008 (or another address) 

,正如評論中已經提到的那樣,只有2顆星就足夠了:

void third(char **msg) { 
    free(*msg); // Free before allocate and change address stored in pointer 
    *msg = malloc(6 * sizeof (char)); 
    strcpy(*msg, "third"); 
    printf("\nthe msg in third after is: %s", *msg); 
} 

void change(char **msg) { 
    free(*msg); // Free before allocate and change address stored in pointer 
    *msg = malloc(7 * sizeof (char)); 
    strcpy(*msg, "change"); 
    printf("\nthe msg in change after is: %s", *msg); 
    third(msg); 
} 

void test(char ** msg) { 
    *msg = malloc(5 * sizeof (char)); 

    strcpy(*msg, "test"); 
    printf("\nthe msg in test after is: %s\n", *msg); 

    change(msg); 
} 

int main(int argc, char** argv) { 

    char * msg; 
    test(&msg); 
    printf("\nthe msg back in main is: %s", msg); 
    free(msg); // Deallocate memory ONLY when you don't need it anymore 
    msg = NULL; // Good practice, set to NULL freed pointer to inform that no more memory are allocated 
} 
+0

好吧,我明白了。那麼釋放內存怎麼樣?免費測試足夠了嗎? –

+0

@JohnRichards我想我的編輯回答你的問題問題 – Garf365