2012-02-01 143 views
1

我試圖實現一個簡單的函數,可以連接任何數量的字符串傳遞給它。我對realloc的調用失敗。是否這樣做是因爲我傳遞給函數的字符串參數存儲在數據段中,realloc看起來是從堆中分配內存的?這只是我的一個想法。我是初學者,所以請原諒,如果它似乎愚蠢。我如何使這個功能運行?realloc()失敗

//Program to implement a function that can concatenate any number of argumnets 

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

char *mstrcat(char *first, ...); 
int main(int argc, int **argv){ 
    char *s; 
    s=mstrcat("I ","Love ","Stack","Overflow"); 
    printf("%s\n",s); 
} 
char *mstrcat(char *first, ...){ 
     char *s=first,*p; 
     int len=0; // stores the length of the string as it grows 
     len=strlen(s); 
     va_list aptr; // creates a pointer to the unnamed argument list 
     va_start(aptr,first); // initialise aptr to the first unnamed argument 
     if(aptr==NULL){ 
     return s; 
     } 
     while((p=va_arg(aptr,char *))!=NULL){ // till there are no more arguments to process 
     len+=strlen(p); 
     if((s=(char *)realloc(s,len+1))!=NULL){ 
      strcat(s,p); 
     } 
     else{ 
      printf("Failed to concatenate\n");  
      return first; 
     } 
     } 
     return s; 
} 
+1

您沒有將NULL作爲mstrcat的最終參數傳遞給此處。這會導致你的循環讀取垃圾數據。這真的是你正在使用的測試案例嗎?如果不是,我們能否看到真正的測試案例? – templatetypedef 2012-02-01 08:49:49

+1

您是通過malloc()或公司分配給mstrcat()的字符串嗎?否則你不能對它們做一個realloc()。正如[here](http://linux.die.net/man/3/realloc)所述:*除非ptr爲NULL,否則它必須早先通過調用malloc(),calloc()或realloc() 。* – m0skit0 2012-02-01 08:53:28

+0

@templatetypedef我添加了'NULL'和下面的代碼行,它工作正常。 'len = strlen(first);''s =(char *)malloc(len + 1);''strcpy(s,first);'。謝謝你的幫助。 – Bazooka 2012-02-01 09:41:23

回答

2

您的代碼有未定義的行爲。該標準要求指針被傳遞到realloc應該與使用存儲器管理功能分配動態存儲器的指針完全匹配。該標準規定的存儲器管理功能是:
aligned_alloc,calloc,mallocrealloc

您傳遞給realloc()的指針未被任何這些指針返回,因此未定義行爲。

參考:
C99標準:7.22.3.5的realloc函數

梗概:#1

#include <stdlib.h> 
void *realloc(void *ptr, size_t size); 

#3

如果ptr爲空指針,realloc函數的行爲與的malloc函數相同指定大小。否則,如果ptr與之前由內存 管理函數返回的指針不匹配,或者如果通過調用free或 realloc函數釋放空間,則行爲未定義爲。如果新對象的內存不能被分配,則舊對象不會被釋放,並且其值不變。

0

一個點約realloc,該size參數是分配的數據,這對您來說應該是老長的s加上p長度(+1當然終止)的新的大小。

正如您懷疑的那樣,您不能使用first字符串作爲重新分配的基礎。在函數的開始處將s設置爲NULL

+0

我相信我在'len + = strlen(p)'步驟中做到了這一點。 – Bazooka 2012-02-01 08:50:50

+0

@Parminder對不起,一開始沒有看到。 – 2012-02-01 08:52:24

0

您正在將字符串文字傳遞給mstrcat函數,它們可能存儲在進程的只讀區域,這意味着它們不能被修改或調整大小。

realloc只能與以前由mallocrealloc返回的指針一起使用。其他類型的用途(與您的一樣)會產生未定義的行爲。

0

mstrcat函數以s指向第一個參數開始。然後你試圖realloc()這個靜態字符串的指針。這不起作用。您只能重新分配以前由malloc()分配的指針。

我建議你改變char *s=firstchar *s=strdup(first)來分配第一個參數的副本,然後這個代碼應該工作。 (提示:你可能想枚舉參數並跟蹤總大小,然後alloc()一個相應的緩衝區,然後連接所有的參數到它)

+0

我同意會有很多更有效的方法來做到這一點,但我更關心學習使用變長參數。它的工作現在很好。感謝您的輸入。 – Bazooka 2012-02-01 09:38:30