19

Could anyone tell me what am i doing wrong over here? Why does my program segfault ? I am trying to insert a third string between string1 and string2.

#include <stdio.h>

int main (void) 
{
char *string1 = "HELLO";
char *string2 = "WORLD";
char *stringX  = "++++";
char *string3;
printf ("%s,%s\n",string1,string2);
sprintf(string3,"%s%s%s",string1,stringX,string2);
printf ("NewVar: %s",string3);
}

Why doesn't sprintf store the resultant value at the memory address pointed by string3? It works when i declare string3 as an ordinary array but not when its a pointer to char array.

I thought string3 wasnt pointing to any memory location, but it does seem to when i do printf("%p",string3);

Output:

# ./concat
HELLO,WORLD,0x40042
4
  • 2
    just as a hint: where should the data be written? Where do you think the pointer points to? Commented Nov 4, 2013 at 16:49
  • @glglgl - I thought string3 wasn't pointing to anything but when i do printf ("%p",string3),it does seem to point to a memory location. Commented Nov 4, 2013 at 16:59
  • But to an unspecified one... Commented Nov 4, 2013 at 18:46
  • @user2953313: What memory address are you talking about? string3 is not pointing to any meaningful memory address. Its value is indeterminate and technically is not memory address at all. It might "seem" to point "to a memory location" but in reality this is just an illusion - a consequence of undefined behavior. Commented Mar 8, 2016 at 0:57

5 Answers 5

43

Imagine you have a pile of cash that you want to put in a briefcase. What do you need? You have to measure the size of the cash to know how big a briefcase to use, and you need a handle to conveniently carry the cash around.

The cash is your strings. The briefcase is memory space. The briefcase handle is the pointer.

  1. Measure your cash: strlen(string1) + strlen(string2) + strlen(stringX). Call this "total".
  2. Now get a big enough briefcase: malloc(total+1)
  3. And put a handle on it: string3

Cobbling all that together...

char *string3 = malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);
sprintf(string3, "%s%s%s", string1, stringX, string2);

So what was wrong with the first attempt? You had no briefcase. You have cash, and you have a handle, but no briefcase in the middle. It appeared to work, in a random kind of way, because the compiler gave you a dirty dumpster to hold the cash. Sometimes the dumpster has room, sometimes it doesn't. When it doesn't, we call that "segmentation fault".

Whenever you have data, you have to allocate space for that data. The compiler allocates space for your constant strings, like "HELLO". But you have to allocate space for strings built at run-time.

Sign up to request clarification or add additional context in comments.

6 Comments

string3 does not point to any writeable memory. The size of char* isn't relevant here - sprintf will try to write to where string3 points to, it will not try to write to the pointer itself.
Hi folks thanks for your explanation.When i print string3 with %p,why does it point to a memory location?When it shouldn't as per the comments above.i have edited my code to highlight this.
@user2953313 C does not initialise your variables to any specific value. The address pointed to is not guaranteed but its likely to be whatever had previously been written to that stack location. Attempting to dereference an uninitialised pointer results in undefined behaviour. Sometimes it will crash; other times it may appear to work.
@user2953313 To get initialization, use calloc() instead of malloc. Working this into my analogy, it's the difference between a used and dirty briefcase (malloc) or a new and clean briefcase (calloc). I start with calloc, then if performance is an issue and cleanlieness is not, I switch to malloc.
What if string1 and string2 is not a string, but an int, for example? You cannot determine the length of the number.
|
10

sprintf does store the value there. The problem is that the pointer string3 has uninitialized value, so you're just overwriting random memory.

One option you have is to use static string buffer:

char string3[20];
snprintf(string3, sizeof(string3), "Hello!");

Or, you can use asprintf on GNU libc-based systems to allocate proper space automatically:

char * string3;
asprintf(&string3, "Hello!");
// ... after use
free(string3); // free the allocated memory

2 Comments

Your asprintf example is incorrect - string3 should be char * not char. It might also be worth adding that asprintf is not a standard C function (or I think even Posix).
@NigelHarper: Thanks, fixed. asprintf is a GNU extension, noted that at well.
9

sprintf does not allocate memory for the string it writes. You have to provide a valid string for it to write into but are currently passing it an uninitialised pointer.

The easiest fix is to change

char *string3;
sprintf(string3,"%s%s%s",string1,stringX,string2);

to

char string3[200];
sprintf(string3,"%s%s%s",string1,stringX,string2);

You may want to guard against buffer overflows in this case by using snprintf instead

char string3[200];
snprintf(string3,sizeof(string3),"%s%s%s",string1,stringX,string2);

Alternatively, you could also cope with larger lengths of source string by determining the size of string3 at runtime, taking care to free this memory when you have finished with it.

char* string3 = malloc(strlen(string1) + strlen(stringX) + strlen(string2) + 1);
if (string3 == NULL) {
    // handle out of memory
}
sprintf(string3,"%s%s%s",string1,stringX,string2);
...
free(string3);

2 Comments

,thanks for the answer using malloc.is that +1 for the null character ?
@user2953313 Glad it helped. Yes, the +1 is for the nul terminator
5

you need to allocate space for string3 either with malloc if you need it to be on the heap, or declare it as a character array if you don't.

Comments

0

suppose you define i as int i; in this level you tell that I will store integer number but still there is not a meaningful number in i variable. like this when you define char *string3 you tell that string3 will store char pointer but still there is not meaningful address. so you must allocate memory to this variable

string3 =  malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.