4

I found a very interesting question.

When I'm using following code:

int main() {
    char * in = "hi, ";
    char str[10];
    strncpy(str, in, 2);
    printf("output = %s", str);
    return 0;
}

My result is nothing, the printf didn't work.

But if I use this:

int main() {
    char * in = "hi, ";
    char * str = malloc(sizeof(char) * 10) ;
    strncpy(str, in, 2);
    printf("output = %s", str);
    return 0;
}

I can get what I expect.

Why does this happen? Is it because of stack and heap? How exactly does that makes this huge difference?

trincot
  • 317,000
  • 35
  • 244
  • 286
windsound
  • 706
  • 4
  • 9
  • 31

3 Answers3

6

The problem - in both cases - is that your string won't be properly terminated after your call to strncpy.

You specify that 2 characters are copied, and your source string in has a length of 4. So strncpy will copy 2 characters, and since that is less than the length of the source string no null terminator will be added - to understand why this is so, review the docs for strncpy:

If count is reached before the entire string src was copied, the resulting character array is not null-terminated.

In this case you'll want:

str[2] = '\0';

after the 'strncpy'.

The second case may seem to work because the buffer that you get from malloc happens to be initialized to all zeros, but you shouldn't rely on this.

Please review the docs for strncpy, noting the exception for null termination, and in general, be careful with string termination!

For even more detail see: Why are strings in C++ usually terminated with '\0'?

Community
  • 1
  • 1
pb2q
  • 58,613
  • 19
  • 146
  • 147
5

The code compiles fine. The run-time error could be because, you haven't terminated the str with null.

From the man page:

The strncpy() function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null terminated.

Add str[2]=0; after the strncpy().

P.P
  • 117,907
  • 20
  • 175
  • 238
1

You could initializing the memory with zeros to be on the "safe" side.

Have a look at the following code,

int main() {
    char * in = "hi, ";
    char str[10]={0};    
    strncpy(str, in, 2);
    printf("output = %s", str);
    return 0;
}

int main() {
    char * in = "hi, ";
    char * str = calloc(10,sizeof(char));
    strncpy(str, in, 2);
    printf("output = %s", str);
    free(str);      //<<Important step
    return 0;
}

str[2] = '\0'; is also a valid solution.

Nathan
  • 674
  • 8
  • 22
  • Thanks for helping, actually, my biggest mistake is that I did double qouted instead of single quote on second edition. Stupid mistake I made causes this XD – windsound Jun 12 '12 at 13:44