0

This program illustrates my question:

#include "stdio.h"
#include "string.h"

void first_try() // segmentation fault
{
    size_t numc = 1;
    char *dest = "i "; // this is bad? i need to declare character array first? why?
    char *src = "lone wolf c program\n";
    memcpy(dest, src, numc);
    printf("%s", dest);
}

void second_try() // works
{
    size_t numc = 1;
    char dest[24] = "i get overwritten";
    char *src = "lone wolf c program\n";
    memcpy(dest, src, 20);
    printf("%s", dest);
}

int main(void)
{
    //first_try(); // run-time error
    second_try();
}

Why does the first_try() method cause a segmentation fault error?

Context

// feel free to ignore this context

I'm still a c programming newb. I went to https://www.devdocs.io and looked at the api for memcpy(). My instinct was to immediately write first_try(). I don't understand the difference between the dest variables in each function. Don't they both contain valid address values?

I read in a "strings as pointers" blog that "the character array containing the string must already exist". Apparently, writing just char *dest = "string"; compiles but is less useful than writing char buf[] = "string"; with a follow-up ptr that can be passed around: char *dest = &buf;. I'd like to understand the 'why' in all of this.

lonious
  • 676
  • 9
  • 25
  • 1
    http://c-faq.com/decl/strlitinit.html – Tom Zych Jun 08 '20 at 05:30
  • See for example [What is the difference between char array and char pointer in C?](https://stackoverflow.com/questions/10186765/what-is-the-difference-between-char-array-and-char-pointer-in-c). – dxiv Jun 08 '20 at 05:32
  • Ah, I knew there had to be a dup out there. My search-fu wasn’t up to it. – Tom Zych Jun 08 '20 at 05:37

1 Answers1

0

In C all literal strings (like your "i ") is really a non-modifiable array containing the characters in the string, plus the null-terminator.

Attempting to modify a literal string leads to undefined behavior.

When you use a pointer for dest

char *dest = "i ";

you make the pointer point to the first element of the three-element array for the string "i ".

When you use it as a destination for memcpy you attempt to modify the contents of this non-modifiable array, leading to undefined behavior and your crash.

This is why you should generally always use const when defining such pointers:

const char *dest = "i ";

When you use an array for the destination, it's allocated in a writable part of the memory for your program and you can modify it as you please.

But please make sure the destination array is large enough to hold the full source string, including the null-terminator. Otherwise your memcpy call will write out of bounds of the allocated memory, and you will again have undefined behavior.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621