Xerif917
Xerif917

Reputation: 132

memcpy causing program to crash with initialized destination

I was working on a larger program and memcpy was causing it to crash. I replicated the situation in a small program and it does the same thing. I noticed that for some reason this program runs fine

// Runs fine
#include <iostream>

int main() {
    char* s1 = "TEST"; // src
    char* s2; // dest

    memcpy(s2, s1, strlen(s1) + 1);
    std::cout << s2 << std::endl; // Should print "TEST"

    return 0;
}

But this program crashes

// Crashes
#include <iostream>

int main() {
    char* s1 = "TEST"; // src
    char* s2 = ""; // dest - Note the small change

    memcpy(s2, s1, strlen(s1) + 1);
    std::cout << s2 << std::endl; // Should print "TEST"

    return 0;
}

I'm not sure why this is happening. Can someone please explain why it is crashing?

Thanks!

Upvotes: 1

Views: 5801

Answers (2)

Both programs have undefined behavior. So if the first one does not crash (it dereferences an uninitialized pointer!), it is just that you are unlucky.

The destination (first argument to memcpy) should be an allocated and writable zone. Either a local array (or some pointer to a local data on the stack, perhaps in some caller's frame) - or some pointer to global or static data - :

char arr[32];
memcpy (arr, s1, strlen(s1)+1);

or a heap-allocated zone:

char*ptr = malloc(32);
if (!ptr) { perror("malloc"); exit(EXIT_FAILURE); };
memcpy (ptr, s1, strlen(s1)+1);

Notice that generally literal strings like "ABC" are not writable. They sit in the read-only data segment.

the above is C code. If you want C++ code, use new (but in C++, you should use std::string)

BTW, be very careful to avoid buffer overflows. The code above works because in that case strlen(s1) is less than 31.

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726799

The reason memcpy is causing an error is that you are trying to copy the content of s1 into a memory pointed to by an a string literal, which is undefined behavior, because string literals are not writable, and even if they were, there wouldn't be enough space.

Your first code is invalid too, because it makes memcpy into a memory pointed to by an uninitialized pointer - an undefined behavior again.

You can fix the first piece of code by adding a call to new, like this:

char* s2 = new char[strlen(s1)+1];

The second piece of code can be fixed like this:

char s2[5] = "";

Upvotes: 3

Related Questions