2012-02-01 91 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