2011-02-03 117 views
1

我可以返回一個在函數內部動態創建的數組(使用malloc)給它的調用者嗎?從函數中返回一個字符數組c

我知道,返回一個靜態分配的數組是錯誤的,因爲隨着函數返回並且變量不再有效,棧會展開,但動態分配的變量又如何?

+0

可以返回一個指針,還是有更復雜的東西,你腦子裏想的? – Swiss 2011-02-03 01:45:41

+3

靜態分配!=自動分配。局部變量具有自動存儲時間。靜態存儲持續時間意味着對象在程序運行的整個過程中都存在(這些對象在文件作用域或在函數中使用`static`聲明)。 – 2011-02-03 01:47:38

回答

5

返回任何分配給malloc的東西都沒有問題,只要使用你的函數的人在完成後自由地處理它。 malloc分配在你的程序中基本上全局的堆上。

0

是的,你可以。只需要malloc()函數內的數組並返回指針。

但是,調用者需要了解它需要在某個時間點被釋放,否則您將發生內存泄漏。

0

你當然可以返回一個分配了malloc的數組,但是你必須確保該函數的調用者最終以free釋放數組;如果您沒有釋放malloc'd數組,則在程序退出之前,內存保持「正在使用」狀態。

3

正如其他人已經指出的,你實際上可以返回一個字符指針。 但是,另一種常見的方法是讓調用者傳入方法的指針以填充長度參數。這使得它負責分配內存的功能也將是負責釋放內存的相同功能,這可以使內存泄漏更容易看到。這是什麼功能,如snprintfstrncpy呢。

/* Performs a reverse strcpy. Returns number of bytes written if dst is 
* large enough, or the negative number of bytes that would have been 
* written if dst is too small too hold the copy. */ 
int rev_strcpy(char *dst, const char *src, unsigned int dst_len) { 
    unsigned int src_len = strlen(src); /* assumes src is in fact NULL-terminated */ 
    int i,j; 

    if (src_len+1 > dst_len) { 
     return -(src_len+1); /* +1 for terminating NULL */ 
    } 

    i = 0; 
    j = src_len-1; 
    while (i < src_len) { 
     dst[i] = src[j]; 
     ++i; 
     ++j; 
    } 
    dst[src_len] = '\0'; 

    return src_len; 
} 

void random_function() { 
    unsigned int buf_len; 
    char *buf; 
    int len; 
    const char *str = "abcdefg"; 

    buf_len = 4; 
    buf = malloc(buf_len * sizeof(char)); 
    if (!buf) { 
     /* fail hard, log, whatever you want */ 
     return; 
    } 

    /* ...whatever randomness this function needs to do */ 

    len = rev_strcpy(buf, str, buf_len); 
    if (len < 0) { 
     /* realloc buf to be large enough and try again */ 
     free(buf); 
     buf_len = -len; 
     buf = malloc(buf_len * sizeof(buf)); 
     if (!buf) { 
      /* fail hard, log, whatever you want */ 
      return; 
     } 
     len = rev_strcpy(buf, str, sizeof(buf)); 
    } 

    /* ... the rest of the randomness this function needs to do */ 

    /* random_function has allocated the memory, random_function frees the memory */ 
    free(buf); 
} 

這可能會導致一些開銷,但如果你不知道你的緩衝區有多大需要,需要兩次調用函數,但經常調用者有一個好主意,有多大的緩衝需求成爲。而且它需要更多的邏輯來確保函數不會超出給定的緩衝區。但它保留了釋放內存的責任,同時也允許選項傳遞本地堆棧內存。

例子只是返回char*

/* Performs a reverse strcpy. Returns char buffer holding reverse copy of 
* src, or NULL if memory could not be allocated. Caller is responsible 
* to free memory. */ 
char* rev_strcpy(const char *src) { 
    unsigned int src_len = strlen(src); /* assumes src is in fact NULL-terminated */ 
    char *dst; 
    int i,j; 

    dst = malloc((src_len+1) * sizeof(char)); 
    if (!dst) { 
     return NULL; 
    } 

    i = 0; 
    j = src_len-1; 
    while (i < src_len) { 
     dst[i] = src[j]; 
     ++i; 
     ++j; 
    } 
    dst[src_len] = '\0'; 

    return dst; 
} 

void random_function() { 
    char *buf; 
    const char *str = "abcdefg"; 

    /* ...whatever randomness this function needs to do */ 

    buf = rev_strcpy(str);   
    if (!buf) { 
     /* fail hard, log, whatever you want */ 
     return; 
    } 

    /* ... the rest of the randomness this function needs to do */ 

    /* random_function frees the memory that was allocated by rev_strcpy */ 
    free(buf); 
}