Thread: memcpy

  1. #1
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838

    memcpy

    Does anyone know what the "rules" are for using memcpy for non-standard data types?

    I ran into problems using combinations of memcpy with the = operator when using AnsiString.

    e.g.:

    Code:
    AnsiString dest;
    AnsiString src1 ="abcdefghijklmnopqrstuvwxyz";
    AnsiString src2 ="0123456789";
    memcpy(&dest,&src1,sizeof(dest));
    memcpy(&dest,&src2,sizeof(dest));
    works fine.

    but something like:

    Code:
    AnsiString dest;
    AnsiString src1 ="abcdefghijklmnopqrstuvwxyz";
    AnsiString src2 ="0123456789";
    memcpy(&dest,&src1,sizeof(dest));
    dest = src2;
    memcpy(&dest,&src1,sizeof(dest));
    produces unpredictable results.

    However, using char * instead of AnsiString works beautifully.

    I have used AnsiString extensively, and while it's not such a big deal to change all of my instances of the class to std::string or char *, the Borland app framework I work with uses AnsiString exclusively, so i would have to have a "mirror" property and setter function every time i want to set any of those instances of Ansistring.

    can someone explain to me what is wrong here, and how i can avoid it, short of always using char *?

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    You want to copy to an array to which you can write.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    i'm not sure i get what you're saying. can you elaborate?

    how could you not write to one?

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    String literals do not live in memory you own. In the code
    Code:
    char *trap = "This is a trap."
    any attempt to write to trap will immediately fail, in flames if the chipset supports it. You can't do
    Code:
    memcpy(trap, buf);
    later on.

    Edit: I don't know anything about AnsiString, but I would suspect a similar fate would befall you.

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Using memcpy() on non-POD data types is wrong. Period. Use std::copy().

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Or use the provided class member assignment operator.
    As in
    dest = src;

    Code:
    struct foo {
      int a;
      int *b;
    };
    Imagine b is allocated to point to a block of memory. If you simply memcpy the pointer, you do NOTHING with the memory being pointed at. Hence everything goes wrong.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    Quote Originally Posted by Salem View Post
    Or use the provided class member assignment operator.
    As in
    dest = src;

    Code:
    struct foo {
      int a;
      int *b;
    };
    Imagine b is allocated to point to a block of memory. If you simply memcpy the pointer, you do NOTHING with the memory being pointed at. Hence everything goes wrong.
    Code:
    typedef struct foo {
      int a;
      int *b;
    }s;
    foo *f = new foo();
    f->b = new int(1);
    f->a = 0;
    memcpy(&f->a,f->b,sizeof(f->a));
    this works

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by m37h0d View Post
    Code:
    typedef struct foo {
      int a;
      int *b;
    }s;
    foo *f = new foo();
    f->b = new int(1);
    f->a = 0;
    memcpy(&f->a,f->b,sizeof(f->a));
    this works
    Yes, that does, essentially, what a "deep copy" constructor would do - and of course, you are only copying the int from one place to another, not the entire struct.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    But that isn't what you asked, you asked how to do

    foo a, b;
    memcpy( &a, &b, sizeof(foo) );
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838

    Post

    Quote Originally Posted by Salem View Post
    But that isn't what you asked, you asked how to do

    foo a, b;
    memcpy( &a, &b, sizeof(foo) );
    that appears to work also.

    Code:
           
    int *val = new int(1);
    typedef struct foo
    {
            int a;
            int *b;
    }s;
    foo f1;
    f1.a = 0;
    f1.b = val;
    foo f2;
    memcpy(&f2,&f1,sizeof(f1));
    *f2.b == 1

  11. #11
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    that appears to work also.
    If by work you mean: "Changing '*f1.b' also changes '*f2.b'." then sure.

    Soma

  12. #12
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    Quote Originally Posted by phantomotap View Post
    If by work you mean: "Changing '*f1.b' also changes '*f2.b'." then sure.

    Soma
    i'm utterly confused. what am i missing here?

    it copies the pointer in f1 to the pointer in f2 so they both point to the same location. what else would you want it to do in that instance?

  13. #13
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Is there any reason why you wouldn't use the assignment operator?

    If a shallow copy is what you want (both pointers pointing to the same memory), that's what you'd get automatically.

    If the class needs a deep copy, it probably has overloaded the assignment operator to do the right thing. Using memcpy in this case breaks the struct/class invariants. If there are any, of course, if there isn't then it's probably not much of an OOP design anyway.

    (A central idea is that a class hides the internal complexity, e.g memory management, from the user of the class. If you use memcpy, the class can no longer guarantee that its internals are intact. An exact copy of the bit-pattern may not be legal: two instances would share the same memory, and there would be no way of telling which instance is responsible for looking after it and cleaning it up. Because you simply copied the bits, it's not even possible for an instance to know that an exact copy exists!)
    Last edited by anon; 04-11-2008 at 11:41 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > what am i missing here?
    What happens is you get into an awful mess if you then try and use the memory which the b member points to.

    f2.b[0] = 42; will also change f1.b[0]

    delete f2.b will also trash f1.b as well, which leaves you with a problem. How do you decide to free f1.b ?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  15. #15
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Dorking around with memcpy() when a perfectly good assignment operator is available is... inexplicable.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Disagreement about memcpy
    By ch4 in forum C Programming
    Replies: 9
    Last Post: 05-28-2009, 10:12 AM
  2. Replies: 14
    Last Post: 06-28-2006, 01:58 AM
  3. Memcpy(); Errors...
    By Shamino in forum C++ Programming
    Replies: 4
    Last Post: 03-24-2006, 11:35 AM
  4. memcpy with 128 bit registers
    By grady in forum Linux Programming
    Replies: 2
    Last Post: 01-19-2004, 06:25 AM
  5. memcpy
    By doubleanti in forum C++ Programming
    Replies: 10
    Last Post: 02-28-2002, 04:44 PM