2017-09-01 132 views
0

我有點困惑與字符指針的概念,所以我做了一個簡單的代碼只是打印由用戶(我)提供了我的名字。我也想練習malloc,所以我引用了指向RAM中某個內存的指針,但是我真的不知道在「sizeof(char)*」之後應該放什麼,因爲這是用戶輸入,尚未確定。 此外,這樣做後,我釋放的內存,但我得到了命令行上一個錯誤消息說:char指針和malloc的

*** Error in `./char': double free or corruption (fasttop): 0x00000000017fe030 *** 
Aborted 

好像我釋放了相同內存的兩倍或東西,但我不知道該怎麼刪除或添加。請幫忙!

#include <stdio.h> 
#include <cs50.h> 

int main (void) 
{ 

    char *strings = malloc(sizeof(char) * 10); 


    printf("What is your name?\n"); 

    //wait for use to type his/her name 
    strings = get_string(); 


    printf("Hello %s\n", strings); 

    free (strings); 

    return 0; 
} 
+3

什麼是get_string?它是否定義了C語言?你應該通過分配的內存來獲取字符串,並在那裏填充數組。不覆蓋。請添加代碼'get_string' –

+0

根據https://cs50.stackexchange.com/questions/21617/whats-the-c-equivalent-for-string-input-getstring的答案,'cs50.h'具有函數名稱是'GetString()'而不是'get_string()'。 – rsp

+1

運行時應該沒有問題,只是內存泄漏。你是否複製並粘貼或重新輸入? – molbdnilo

回答

6

strings = get_string();實際上分配由get_string()返回到strings值。它不會將它寫入您分配的內存中。

因此,由malloc()返回的值已被覆蓋(並在此情況下丟失)。

free(strings)被釋放任何get_string()返回。這個問題沒有提供代碼,但大概它是無效的free()它。

因爲運行時間告訴你它被釋放兩次我猜你已經在get_string()中分配了內存,然後釋放它並返回一個無效指針。

如果你要使用的內存分配,你需要更改get_string()接受指針:

void get_string(char *str){ 
    //Do whatever writing you value into str[] as an array of char.. 
} 

良好做法是有:

void get_string(char *str, size_t max){ 
    //Do whatever writing you value into str[] as an array of char.. 
    //Use max to avoid writing beyond the end of the space allocated... 
} 

然後調用爲get_string(strings,10);

編輯:經過一番研究,已發現缺陷。 get_string()不直接free()返回,但它增加了其在退出釋放由圖書館進行的分配列表(在一個名爲teardown()atexit()或其他編譯器相關的功能註冊的函數)的字符串。

也就是說設計差,因爲消費者提供代碼,本身沒有安全的方式釋放其在典型使用情況下不會被要求爲整個應用程序運行內存。 get_double()更糟糕的是,因爲它永遠不會返回分配的數據,但從來沒有重用它,無異於直接內存泄漏。

的代碼應該:

  1. 順應文檔,並要求消費者代碼free()字符串(也許將其重命名爲說get_string_alloc()爲清楚起見)。
  2. 發售庫程序來釋放字符串(get_new_string()release_string()

沒有轉向用C分配內存的所有權,但持有到它的執行剩餘非常好的方式絕對不是答案。 許多圖書館去圓的房屋推到分配代碼的消費者,但是這是繁重時所需的空間的全尺寸不能被稱爲諸如這裏。

我建議把_alloc()放在任何返回消費者代碼必須稍後必須free()的對象的末尾。

所以提出的問題的答案是刪除malloc()free(),因爲庫處理兩者。但是,如果你的程序,使該功能很多電話和其他人的內部依賴它(如get_double()),你可能耗盡內存,因爲該庫是坐在死角提防。

+1

「推測它是無效的釋放()它。」 - [不幸的是,它*是*有效的](https://reference.cs50.net/cs50/get_string)。我繼續懷着我最大的願望,扼殺設計'cs50.h'庫的惡魔,原因有很多,包括但不限於'typedef char * string;'那裏的權利應該告訴你這個頭是多麼不光彩。 – WhozCraig

+0

@WhozCraig然後我認爲在cs50代碼中可能有問題。你不應該在做'malloc()',因爲docco說它分配空間。但僅僅因爲你的代碼泄露了10個字節,不應該導致消息說你已經釋放了一些東西。它可能只是在執行結束時發出一個錯誤,一個10字節的塊沒有被釋放。 你從哪裏得到代碼?你能發佈'get_string()'的源嗎? – Persixty

+3

顯然,根據您使用的cs50版本,[庫可能會從'get_string']管理自己的堆分配鏈(https://github.com/cs50/libcs​​50/blob/develop/docs/get_string.adoc ),並在進程退出時釋放它們(毫無意義,因爲操作系統將回收所有內存而不考慮)。在這樣做的時候,如果在用戶代碼中也做了雙免費的話。不同版本的庫不這樣做。因此,遵循舊教程的人會編寫代碼,使用更新的lib會產生一個雙免費的代碼。這可能是這裏發生的事情。 – WhozCraig

0

你不包括get_string()代碼,但你覆蓋strings與它的返回值是錯誤的。您傳遞給free()地址必須來自malloc(),似乎你違反該(除了失去原來的返回地址爲您10個字節)。

假設get_string()返回靜態存儲器(即您不需要釋放它),您可以在不涉及malloc()的情況下執行此操作。

如果你真的想,這樣的事情可能工作:

printf("What is your name?\n"); 
const char *name = get_string(); 
const size_t nlen = strlen(name); 
char * const name_copy = malloc(nlen + 1); 
if(name_copy != NULL) 
{ 
    memcpy(name_copy, name, nlen + 1); 
    printf("Hello %s (from my own memory!)\n", name_copy); 
    free(name_copy); 
} 

這是頗爲曲折,但你的想法。

+0

這個假設是錯誤的:'get_string'返回調用者必須釋放的內存。您可以簡單地使用'strdup'作爲複製部分。 ;) – Gerhardh

2

的問題是你的get_strings覆蓋您最初malloc。指針值是一個值。通過與別的東西等同,你更換malloc值。

0

首先,你必須創建將由*串指出動態存儲器。但是然後你使用*字符串指針指向本地字符串(來自get_string()函數)。當你調用free時,程序試圖刪除本地(堆棧)引用並拋出錯誤。

爲了解決這個錯誤,程序應該是

#include <stdio.h> 
#include <cs50.h> 

int main (void) 
{ 

char *strings = malloc(sizeof(char) * 10); 


printf("What is your name?\n"); 

//wait for use to type his/her name 
strcpy(strings, get_string());  // Use strcpy instead of assigning 


printf("Hello %s\n", strings); 

free (strings); 

return 0; 
} 
0

內存在所述語句的字符串= get_string分配(); 。你不要有它的malloc(字符*字符串=的malloc(的sizeof(字符)* 10); )。沒有的malloc它會正常工作

0

char *strings;

  • 無需新的malloc返回的字符串從get_string()函數已經在堆上,你只需要拿起指向第一個字符的指針。(get_string() function reference

strings = get_string();

printf(「Hello%s \ n」,strings);

  • 打印字符串後,你應該釋放分配給它的內存,因爲它是在get_string()函數的引用說明上堆(通過malloc的)

存儲串;內存必須由調用者釋放到 避免泄漏。

我覺得一切是好的,試試這個代碼:

#include <stdio.h> 
#include <cs50.h> 

    int main (void) 
    { 
     char *strings; 

     printf("What is your name?\n"); 

     //wait for use to type his/her name 
     strings = get_string(); 

     printf("Hello %s\n", strings); 

     free (strings); 

     return 0; 
    } 
+0

我同意不需要'malloc'並導致內存泄漏。但是,這怎麼會導致錯誤消息「雙倍免費」? – Gerhardh

+0

@Gerhardh問題是,編譯器獲取在麻煩,因爲他會覆蓋指針的char *字符串= malloc的(的sizeof(char)的* 10);從這個malloc獲得get_string()返回指針值,所以他自動丟失了一個指針,用來釋放他最初配對的指針,現在它仍然沒有被釋放。 – Lazar

+0

我知道,但是內存泄漏是基本上什麼是「雙自由或已損壞」錯誤通常表示相反。該錯誤消息指示某些內存已釋放兩次或內存邊界被覆蓋。該錯誤消息與該內存泄漏不匹配。必須有別的東西。這是相當奇怪給出的一小段代碼... – Gerhardh