2

I'm (obviously) learning C

I don't understand why would I use malloc to allocate memory for a newly copied string (they did it in cs50 memory lecture)

#include <stdio.h>
#include <stdlib.h>

int main(){
    char *s = "Hi";
    char *t; // Why the need for char *t malloc(3) here ??
    strcpy(t,s);
    printf("%s",t); // prints "Hi"
    return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
manhoty
  • 59
  • 5
  • `t` is supposed to point to some *valid* memory that is able to contain the string. `malloc` is providing it. In your code it contains just some garbage value which is definitely not a valid memory address (or not an address of a memory location you can legitimately write to ). – Eugene Sh. Dec 16 '21 at 18:49
  • `strcpy()` doesn't allocate memory for the new string. It copies the string into memory that must be provided. – Barmar Dec 16 '21 at 18:50
  • 2
    "_prints "Hi"_" is just one possibility when you have _undefined behavior_. It doesn't have to print `HI`. – Ted Lyngmo Dec 16 '21 at 18:53
  • @EugeneSh. Thanks, But when I print the content in `t` it shows the copied string, Im not sure what do you mean by garbage – manhoty Dec 16 '21 at 18:54
  • 4
    `t` is a local variable. An uninitialized one. Such a variables have indeterminate values (garbage in slang). In your case it happened to contain some value that could be interpreted as some address of some memory that could be written. But it could also be an address of some memory mapped peripheral which would launch a nuke missile upon the string `"Hi"` is written into it. – Eugene Sh. Dec 16 '21 at 18:57
  • @EugeneSh. wouldn't `t = "xyz";` override whatever garbage is there and replace it with `xyz` ? why does it crash or explode ? – manhoty Dec 16 '21 at 19:32
  • 1
    This is not what you did, right? `t="xyz"` does overwrite `t` with an address of static string `"xyz"`. `strcpy` does not change the value of `t`, but the value it is pointing to. – Eugene Sh. Dec 16 '21 at 19:33

2 Answers2

4

The first declaration: char *s = "Hi"; does not need a malloc because at compile time, the compiler will set s to be pointing at a string literal that will already have a designated place in memory.

The second declaration: char *t; does not get assigned to point at anything. You COULD copy the contents of s into t and maybe everything would work, but you would be copying the contents of s into some random section of memory that t is initially pointed to which your your OS hasn't allocated to you. Most likely causing a segfault and crashing.

That's what malloc does, it makes a request for a number of bytes to be allocated to your program on the heap, then returns a pointer to the starting address of that memory (or NULL if it failed to allocate memory for any reason), allowing you to safely use it if the request succeeded.

codyne
  • 552
  • 1
  • 9
0

What you are doing is called UB, Undefined Behavior. You should ALWAYS allocate the necessary memory for a strcpy.

In fact, you have not even included string.h, your code will not work as strcpy will be an undefined function.

Even if it somehow due to some bug worked, you would ALWAYS get a segmentation fault. You only have 3 bytes allocated, all of which are taken. Your code is exploitable and is a security vulnerability given malicious input

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

int main(void)
{
    char *e = malloc(3);

    char *b;

    strcpy(e, "Hi"); // 3 bytes

    strcpy(b, e);

    fputs(b, stdout);
}

Segmentation error. We are writing 3 bytes to a region of 0 bytes. (strcpy(b, e))

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

int main(void)
{
    char *e = "Hi";

    char *b;

    strcpy(b, e);

    fputs(b, stdout);

}

Segmentation error. Same thing.

Even running your code with string.h,


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

int main(){
    char *s = "Hi";
    char *t; // Why the need for char *t malloc(3) here ??
    strcpy(t,s);
    printf("%s",t); // prints "Hi"
    return 0;
}

Guess what? Segmentation error.

I am sorry for being harsh, but this is a very important topic new to C users need to learn, as it can introduce security vulnerabilities and unpleasant coding experiences.

ALWAYS validate inputs, and ALWAYS have the necessary space allocated.

If you are having a seg fault, one of the best tools is Valgrind or Asan.

Valgrind you will have to look up on your own, but Asan is: gcc -fsanitize=address filename -o filename -g This will catch all buffer overflows making your life much more pleasant. You must include -g, which attaches your code to the compiled file so Asan can tell you which line your program is failing on.

Chris
  • 154
  • 8