17

Is it safe to do something like the following?

#include <stdio.h>
#include <malloc.h>
#include <string.h>

int main(void)
{
    char* msg;

    strcpy(msg, "Hello World!!!");  //<---------

    printf("%s\n", msg);

    return 0;
}

Or should the following be used?

char* msg = (char*)malloc(sizeof(char) * 15);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
LEH
  • 211
  • 1
  • 2
  • 5
  • 5
    You need the malloc, otherwise msg is just a dangling pointer. – Paul R Mar 18 '11 at 16:28
  • 3
    Use `malloc`, but remove the cast and `sizeof(char)`. The correct usage is `char *msg = malloc(15);` – R.. GitHub STOP HELPING ICE Mar 18 '11 at 16:30
  • Also `malloc()` is declared in `` not `` – pmg Mar 18 '11 at 18:10
  • And the return value from `malloc()` should **ALWAYS** be checked: `char *msg = malloc(15); if (msg == NULL) /* not ok to proceed */;` – pmg Mar 18 '11 at 18:13
  • 1
    @MateuszPiotrowski: if you don't check you have no way of knowing whether it "worked". Returning `NULL` is malloc's way of telling you something went wrong. – pmg May 23 '15 at 21:44
  • For people (like me) curious why omitting `sizeof(char)` is OK in this instance (as in @R..'s comment): [This question](https://stackoverflow.com/q/2215445/1110928) explains that `sizeof(char)==1` per the C99 standard. – apnorton Jun 20 '17 at 15:05

6 Answers6

36

strdup does the malloc and strcpy for you

char *msg = strdup("hello world");
pm100
  • 48,078
  • 23
  • 82
  • 145
  • 2
    strdup is not C standard, not C89 and not C99 – user411313 Mar 18 '11 at 17:54
  • 13
    POSIX is a standard. There are a lot of things that we use that aren't C89 or C99. That isn't reason not to use something so simple. Please use strdup before writing a dense macro like MYSTRDUP(). strdup takes 1 line to implement as a function, and frankly, should be in the standard. – codenheim Apr 21 '14 at 18:59
  • 2
    Certainly, but it is worth mentioning that this is in POSIX. – Tor Klingberg Oct 13 '15 at 15:24
  • just had weird issues with strdup but only on Win 10, malloc+strcpy instead then it works?! – colin lamarre Dec 18 '18 at 10:54
  • 4
    I would be *very* suspicious of a statement like 'just had weird issues with strdup'. – pm100 Dec 18 '18 at 16:55
  • Don't quote me on this but I think the reason it isn't in the C standard is because it allocates memory and only the malloc/calloc set of operators are supposed to do that. Otherwise, it causes a side effect. This is why it has never been included. – Jon Scobie Sep 15 '20 at 15:29
  • `strdup` is included in C2x. https://en.cppreference.com/w/c/string/byte/strdup – jcsahnwaldt Reinstate Monica Nov 09 '20 at 23:15
12

Your original code does not assign msg. Attempting to strcpy to it would be bad. You need to allocate some space before you strcpy into it. You could use malloc as you suggest or allocate space on the stack like this:

char msg[15];

If you malloc the memory you should remember to free it at some point. If you allocate on the stack the memory will be automatically returned to the stack when it goes out of scope (e.g. the function exits). In both cases you need to be careful to allocate enough to be able to copy the longest string into it. You might want to take a look at strncpy to avoid overflowing the array.

qbert220
  • 11,220
  • 4
  • 31
  • 31
  • if the size of msg is less than the string's length, say "char msg[3]; strcpy(msg, "abcdefg");", would be ok? If now, I cout msg, will the output be "abcdefg"? – Alcott Sep 16 '11 at 12:56
  • 1
    No it will not. `char msg[3]` allocates space for 3 characters. You cannot copy 8 characters into that space (7 letters plus a null terminator). – qbert220 Sep 16 '11 at 14:07
2

The first version is not safe. And, msg should be pointing to valid memory location for "Hello World!!!" to get copied.

char* msg = (char*)malloc(sizeof(char) * 15);
strcpy(msg, "Hello World!!!");
Mahesh
  • 34,573
  • 20
  • 89
  • 115
2

Use:

#define MYSTRDUP(str,lit) strcpy(str = malloc(strlen(lit)+1), lit)

And now it's easy and standard conforming:

char *s;
MYSTRDUP(s, "foo bar");
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user411313
  • 3,930
  • 19
  • 16
1
 char* msg;
 strcpy(msg, "Hello World!!!");  //<---------Ewwwww
 printf("%s\n", msg); 

This is UB. No second thoughts. msg is a wild pointer and trying to dereference it might cause segfault on your implementation.

msg to be pointing to a valid memory location large enough to hold "Hello World".

Try

char* msg = malloc(15);
strcpy(msg, "Hello World!!!");

or

char msg[20]; 
strcpy(msg, "Hello World!!!");
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
0

You need to allocate the space. Use malloc before the strcpy.

SDReyes
  • 9,798
  • 16
  • 53
  • 92