Thread: Question about memcpy

  1. #1
    Registered User
    Join Date
    Nov 2010
    Posts
    44

    Question about memcpy

    Hi I would like to understand how memcpy works when dealing with a sequence of characters and integers

    the definition of memcpy is the following:

    Code:
    void * memcpy ( void * destination, const void * source, size_t num );
    so having the destination and the source, we copy num bytes from the source(which is an address in the main memory) to the address pointed by the variable destination

    so we have

    source points to A(which is an address)
    destination points to B(address)

    let's say num = 3

    we copy 3 bytes which start from A address and finish in some address A + x to the B address

    so finally we will have B + x reserved for the 3 bytes correct?

    suppose we have this code

    Code:
    #include <iostream>
    using namespace std;
    
    int main(void){
    
    	char* a = "123";
    
    	int value = 0;
    	memcpy(&value, a, sizeof(int));
    
    	cout<<a<<endl;
    	cin.get();
    
    	return 0;
    }
    I want to copy the number 123 to the integer value

    which works fine but when I try to do the opposite, it doesn't

    Code:
    #include <iostream>
    using namespace std;
    
    int main(void){
    
    	char* a = "";
    
    	int value = 1234;
    	memcpy(a, &value, sizeof(int));
    
    	cout<<a<<endl;
    	cin.get();
    
    	return 0;
    }
    it gives me an exception

    if I use an array instead

    Code:
    #include <iostream>
    using namespace std;
    
    int main(void){
    
    
    	char a[4] = "";
    
    	int value = 1234;
    	memcpy(a, &value, sizeof(int));
    
    	cout<<a<<endl;
    	cin.get();
    
    
    
    
    	return 0;
    }
    it gives me the same exception...

    the exception is access violation writing location 0x0034234..

    can someone please explain me why?

    Thanks in advance

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    memcpy() does not reserve anything. If source and destination each have only two bytes allocated to them, and you tell memcpy() to copy four bytes, the result is undefined behaviour. That is a factor in all of your examples, depending on sizeof(int).

    All three of your examples have undefined behaviour. Unfortunately, sometimes, undefined behaviour can manifest in a way that makes sense to you.

    The second and third examples also have undefined behaviour because they force memcpy() to write to a string literal. A string literal is const, so should not be written to.

    Also, even if you eliminate the factors that give undefined behaviour ..... given an int of the value 1234, memcpy() will never produce a set of characters '1', '2', '3', '4'. If you want that mapping, use sprintf() or some other function that formats the integer to produce a string.
    Last edited by grumpy; 04-02-2012 at 03:14 PM.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Firstly, do you understand what's happening here? Take your first chunk of code. When you memcpy the bytes stored at address a to the address of value you are not actually putting the number 123 into value, just the 4 or 8 (depending on your sizeof(int)) bytes starting at a. Also note that the string "123" has 4 bytes, including the terminating zero byte. If your sizeof(int) is 8, you will actually be copying another 4 bytes which you shouldn't be accessing, but that will not necessarily cause a segfault.

    Assuming that you understand that, then your second chunk of code doesn't work because you're trying to write to unwritable memory (where string literals are stored), and even if it would work, you haven't set aside enough bytes. A null string, "", will only set aside 1 byte for the zero terminator.

    Your 3rd chunk of code doesn't segfault on my (old) computer. But if it does so on yours, then your ints are probably 8 bytes, so you need to set aside 8, not 4, bytes.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  4. #4
    Registered User
    Join Date
    Nov 2010
    Posts
    44
    Thanks for your answers

    Quote Originally Posted by grumpy View Post
    memcpy() does not reserve anything. If source and destination each have only two bytes allocated to them, and you tell memcpy() to copy four bytes, the result is undefined behaviour. That is a factor in all of your examples, depending on sizeof(int).
    In the first example doesn't it have 4 bytes allocated? I mean for a string we have 3 characters, and also the null pointer at the end

    so I have 4 bytes

    for the second you are correct but in the 3 again I think I have 4 bytes allocated with the array

    Quote Originally Posted by grumpy View Post
    All three of your examples have undefined behaviour. Unfortunately, sometimes, undefined behaviour can manifest in a way that makes sense to you.

    The second and third examples also have undefined behaviour because they force memcpy() to write to a string literal. A string literal is const, so should not be written to.

    Also, even if you eliminate the factors that give undefined behaviour ..... given an int of the value 1234, memcpy() will never produce a set of characters '1', '2', '3', '4'. If you want that mapping, use sprintf() or some other function that formats the integer to produce a string.
    About the const now I udnerstand, however as you said I eliminated those factors by using the array
    Code:
     char a[4] = {'a','b','c','\0'};
    and it didn't work

    Quote Originally Posted by oogabooga
    Firstly, do you understand what's happening here? Take your first chunk of code. When you memcpy the bytes stored at address a to the address of value you are not actually putting the number 123 into value, just the 4 or 8 (depending on your sizeof(int)) bytes starting at a. Also note that the string "123" has 4 bytes, including the terminating zero byte. If your sizeof(int) is 8, you will actually be copying another 4 bytes which you shouldn't be accessing, but that will not necessarily cause a segfault.
    why does it print the correct result though? I mean I get the correct value in the "value" variable which is 123..
    Quote Originally Posted by oogabooga
    Assuming that you understand that, then your second chunk of code doesn't work because you're trying to write to unwritable memory (where string literals are stored), and even if it would work, you haven't set aside enough bytes. A null string, "", will only set aside 1 byte for the zero terminator.

    Your 3rd chunk of code doesn't segfault on my (old) computer. But if it does so on yours, then your ints are probably 8 bytes, so you need to set aside 8, not 4, bytes.
    I made a cout to the sizeof(int) and I got 4 as a result however it still prints an error, I use Visual studio 2008.

  5. #5
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    why does it print the correct result though? I mean I get the correct value in the "value" variable which is 123..
    You're not printing value, you're printing a! Change it to value and see what you get.

    I made a cout to the sizeof(int) and I got 4 as a result however it still prints an error, I use Visual studio 2008.
    What do you mean by "prints an error"? Do you mean the program crashes or that it prints garbage. It should basically just print garbage, since that's essentially what you've put into the variable.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  6. #6
    Registered User
    Join Date
    Nov 2010
    Posts
    44
    You are correct sorry. It prints garbage. I still kind of don't understand how mem copy works on int and chars. I understand why it works in chars, but since we copy bytes why doesn't it work with int and chars?

    I will have to research more about it because some sites just have simple examples and don't go any deeper into the subject

  7. #7
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    The string "123" is actually the bytes (assuming ascii and using decimal) : 49, 50, 60, 0.
    Simply copying those bytes into the memory reserved for an int does not produce the numeric value 123.
    The value 123 in memory (assuming 4 bytes) would be either: 0, 0, 0, 123 or 123, 0, 0, 0.
    The first is called "big endian" (because the most significant byte, or big end, comes first) while the second is called "little endian".

    So basically, the string representation of a number and the actual number are two different things.
    To convert from a number to its string representation you use printf (and associated functions).
    To go the other way, you use scanf (and cousins), or perhaps atoi(), etc.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  8. #8
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Memcpy is the most brute force copy available without pure assembly. As with most C functions there are no bounds checks on source or destination and it will be happy to overwrite memory that is not allocated to your dest buffer or to anyone for that matter. Note that in debug mode you will probably get away with this since debug memory has tons of extra space in it and headers to assist with debugging. Release mode, however, is much more finicky and if you run this in release I would venture to guess it will crash.

    If my assembly memory serves me a memcpy in its purest form is a simple rep movsd with the count in eax, source in es, and dest in ds. MSVS memcpy does some more checking before all of that and is not quite as simple. It checks for copies from higher to lower addresses and vice versa to achieve the best copy it can muster. You can view the source by viewing the assembly output of your code that calls memcpy.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. memcpy question
    By absoult-tech1 in forum C Programming
    Replies: 5
    Last Post: 10-03-2010, 12:24 PM
  2. quick memcpy question
    By newbie30 in forum C Programming
    Replies: 3
    Last Post: 01-25-2010, 01:01 PM
  3. memcpy question
    By newbie30 in forum C Programming
    Replies: 2
    Last Post: 12-09-2009, 08:37 AM
  4. Quick question on sprintf and memcpy
    By vandrea in forum C Programming
    Replies: 5
    Last Post: 08-23-2009, 12:53 PM
  5. A tiny question about memcpy
    By Kelvin in forum C++ Programming
    Replies: 8
    Last Post: 07-23-2002, 03:59 PM