'strcpy' with 'malloc'?
Asked Answered
I

6

18

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);
Isolative answered 18/3, 2011 at 16:25 Comment(6)
You need the malloc, otherwise msg is just a dangling pointer.Tola
Use malloc, but remove the cast and sizeof(char). The correct usage is char *msg = malloc(15);Hung
Also malloc() is declared in <stdlib.h> not <malloc.h>Protractile
And the return value from malloc() should ALWAYS be checked: char *msg = malloc(15); if (msg == NULL) /* not ok to proceed */;Protractile
@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.Protractile
For people (like me) curious why omitting sizeof(char) is OK in this instance (as in @R..'s comment): This question explains that sizeof(char)==1 per the C99 standard.Genro
P
13

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.

Phonogram answered 18/3, 2011 at 16:29 Comment(2)
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"?Halflength
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).Phonogram
T
39

strdup does the malloc and strcpy for you

char *msg = strdup("hello world");
Transcendent answered 18/3, 2011 at 16:31 Comment(7)
strdup is not C standard, not C89 and not C99Doorman
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.Numerary
Certainly, but it is worth mentioning that this is in POSIX.Hyksos
just had weird issues with strdup but only on Win 10, malloc+strcpy instead then it works?!Indecorous
I would be very suspicious of a statement like 'just had weird issues with strdup'.Transcendent
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.Topflight
strdup is included in C2x. en.cppreference.com/w/c/string/byte/strdupBuggs
P
13

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.

Phonogram answered 18/3, 2011 at 16:29 Comment(2)
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"?Halflength
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).Phonogram
F
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!!!");
Fulbert answered 18/3, 2011 at 16:27 Comment(4)
don't cast the return of malloc and don't use sizof(char).Psychodiagnostics
why not sizeof(char)?Transcendent
char is guaranteed to be 1 byte in cCoatbridge
@Coatbridge so sizeof(char) is both correct and clear but redundant. No need to say 'dont use'Transcendent
D
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");
Doorman answered 18/3, 2011 at 17:57 Comment(2)
except in the case that malloc failedTranscendent
missing a (char*) cast #define MYSTRDUP(str,lit) strcpy(str = (char*)malloc(strlen(lit)+1), lit)Boarder
S
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!!!");
Sanitation answered 18/3, 2011 at 16:37 Comment(1)
(UB == undefined behavior)Moreville
P
0

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

Pons answered 18/3, 2011 at 16:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.