Reputation: 1458
I was trying to implement a simple function that can concatenate any number of strings passed to it. My call to realloc fails. Is it something to do with the fact that the string arguments that i pass to the function are stored in data segment where as realloc looks to allocate memory from the heap ? This is just an idea i have. I'm a beginner so please excuse if it seems stupid. How can i make this function run ?
//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;
}
Upvotes: 1
Views: 1594
Reputation: 330
the mstrcat function is starting with s pointing to the first argument. Then you are trying to realloc() this pointer which is a static string. This will not work. You can only realloc a pointer previously allocated by malloc().
I suggest you change char *s=first
to char *s=strdup(first)
to allocate a copy of the first argument, and then this code should work.
The concatenation algorithm is pretty inefficient, but that's another story... (hint: you may want to enumerate the arguments and keep track of the total size, then alloc() a corresponding buffer and then concatenate all the arguments into it)
Upvotes: 0
Reputation: 206508
Your code has an Undefined Behavior. The standard mandates that the pointer being passed to realloc
should exactly match the pointer which was allocated dynamic memory using a memory management function. Memory management functions specified by the standard are:
aligned_alloc
, calloc
, malloc
, and realloc
.
The pointer you are passing to realloc()
was not returned by any of these and hence the Undefined Behavior.
Reference:
c99 standard: 7.22.3.5 The realloc function
Synopsis: #1
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
#3
If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to the free or realloc function, the behavior is undefined. If memory for the new object cannot be allocated, the old object is not deallocated and its value is unchanged.
Upvotes: 2
Reputation: 43498
You are passing string literals to your mstrcat
function, and they are probably stored in a read-only area of the process, which means that they cannot be modified or resized.
realloc
can only be used with a pointer previously returned by malloc
or realloc
. Other kinds of uses (as is yours) yield undefined behaviour.
Upvotes: 0
Reputation: 409136
A point about realloc
, the size
argument is new size of the allocated data, which for you should be the old length of s
plus the length of p
(+1 for the terminator of course).
And as you suspect, you can not use the first
string as the base of the reallocations. Instead set s
to NULL
at the start of the function.
Upvotes: 0