Thread: Multidimentional structs + memcpy() == FAIL

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    161

    Multidimentional structs + memcpy() == FAIL

    Ok, I've got structs and arrays of structs together here, and using memcpy to fill one of the secondary structs erases the whole goddamn struct, not just the secondary one. Example code is below. When memcpy is called on the Defaults.System struct, it erases all of Defaults while setting Defaults.System.

    I thought I'd work around it by writing a copy function of my own, but I can't figure out how to declare a function to send pointers to the system_vars structs I want copied.

    Code:
    struct system_vars {
        int SysId;
        int OpSize;
        int fType;
        int Language;
        int HeaderLen;
        u32 vOffset;
        u32 AddrMask;
        int Endian;
    } SysVars[7];
    
    struct ini {
        LOGFONT lvFontInfo;
        int MainWidth;
        int MainHeight;
        int MainStatus;
        WINDOWPLACEMENT MainPlacement;
        struct system_vars System;
        struct system_vars UserSys[1];
        int RegView;
        int RegAlign;
    } Settings, Defaults;
    Code:
        memset(&Defaults,0,sizeof(Defaults));
        memset(&Settings,0,sizeof(Settings));
        memset(&SysVars,0,sizeof(SysVars));
        Defaults.lvFontInfo = (LOGFONT){ 0, 0, 0, 0, 0, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_MODERN, "Terminal"} ;
        Defaults.MainPlacement.length = sizeof(WINDOWPLACEMENT);
        Defaults.RegView = MNU_REGVIEW0;
        Defaults.RegAlign = MFS_CHECKED;
        SysVars[PS2_ELF].SysId = PS2_ELF;
        SysVars[PS2_ELF].OpSize = 4;
        SysVars[PS2_ELF].Language = R5900;
        SysVars[PS2_ELF].fType = ELF_FILE;
        SysVars[PS2_ELF].Endian = LITTLE_ENDIAN32;
        
        SysVars[PS2_RAW].SysId = PS2_RAW;
        SysVars[PS2_RAW].OpSize = 4;
        SysVars[PS2_RAW].Language = R5900;
        SysVars[PS2_RAW].fType = RAW_FILE;
        SysVars[PS2_RAW].Endian = LITTLE_ENDIAN32;
    
        SysVars[N64_ROM].SysId = N64_ROM;
        SysVars[N64_ROM].OpSize = 4;
        SysVars[N64_ROM].Language = R4300i;
        SysVars[N64_ROM].HeaderLen = 0x40;
        SysVars[N64_ROM].vOffset = 0x00000040;
        SysVars[N64_ROM].fType = N64ROM_FILE;
    
        SysVars[N64_RAW_LE].SysId = N64_RAW_LE;
        SysVars[N64_RAW_LE].OpSize = 4;
        SysVars[N64_RAW_LE].Language = R4300i;
        SysVars[N64_RAW_LE].AddrMask = 0x80000000;
        SysVars[N64_RAW_LE].fType = RAW_FILE;
        SysVars[N64_RAW_LE].Endian = LITTLE_ENDIAN32;
    
        SysVars[N64_RAW_BE].SysId = N64_RAW_BE;
        SysVars[N64_RAW_BE].OpSize = 4;
        SysVars[N64_RAW_BE].Language = R4300i;
        SysVars[N64_RAW_BE].AddrMask = 0x80000000;
        SysVars[N64_RAW_BE].fType = RAW_FILE;
        SysVars[N64_RAW_BE].Endian = BIG_ENDIAN;
    
        SysVars[PS1_RAW].SysId = PS1_RAW;
        SysVars[PS1_RAW].OpSize = 4;
        SysVars[PS1_RAW].Language = R3000;
        SysVars[PS1_RAW].AddrMask = 0x80000000;
        SysVars[PS1_RAW].fType = RAW_FILE;
        SysVars[PS1_RAW].Endian = LITTLE_ENDIAN32;
    
        memcpy(&Defaults.System,&SysVars[PS2_ELF],sizeof(SysVars[PS2_ELF]));
    ;

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Does
    Defaults.System = SysVars[PS2_ELF];
    work?

    You can assign structures of the same type.
    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.

  3. #3
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Code:
    memcpy(&Defaults.System,&SysVars[PS2_ELF],sizeof(SysVars[PS2_ELF]));
    Ahem, the sizeof should be of Defaults.System. You want to make sure you don't copy more than the destination buffer can hold. Bad things would happen...

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I'm with salem on this one: use struct assignment - if anything, it's probably a little bit faster/shorter code than the call to memcpy() [unless the compiler does the same thing for both anyways].

    QuantumPete: It should be the same for sizeof(Defaults.System) and sizeof(SysVars[PS2_ELF]).

    Further, I managed to make a compilable program out of the code supplied, and it works as I expect it to. Perhaps Viper187 could provide us with a piece of code that can be compiled, that shows the problem.

    --
    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.

  5. #5
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    Quote Originally Posted by matsp View Post
    QuantumPete: It should be the same for sizeof(Defaults.System) and sizeof(SysVars[PS2_ELF]).
    Of course, it *should*. But it's always a good habit to put the destination buffer's size. It doesn't matter in this program, but it will somewhere in the future. It's like initialising your variables: not strictly necessary, but it will save you one day. I've seen plenty of bugs that were caused by both.

    QuantumPete
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  6. #6
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    dammit. 1 memcpy is working, but the other 2 aren't. It's the array of structs that's messing it up with memcpy...

    Code:
        Defaults.RegView = MNU_REGVIEW0;
        memcpy(&Defaults.System,&SysVars[PS2_ELF],sizeof(SysVars[PS2_ELF])); //this works
        memcpy(&Defaults.UserSys[0],&SysVars[PS2_ELF],sizeof(SysVars[PS2_ELF])); //this ........s up Defaults.RegView (and everything else)
        memcpy(&Defaults.UserSys[1],&SysVars[PS2_ELF],sizeof(SysVars[PS2_ELF]));
        Defaults.UserSys[0].SysId = UserMode1; //even this line seems to screw up RegView.
    Well, aint that interesting. If I declare the 2 structs within Defaults at the end of it, the other vars are seemingly unmolested. Apparently there's some issue with the struct not knowing how goddamn big it's supposed to be despite a sizeof() that should bloody work. I even tried sizeof(struct sys_vars). nada.
    Last edited by Viper187; 06-17-2008 at 10:14 AM.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    You've only got ONE UserSys, so the 2nd one will surely barf.
    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.

  8. #8
    Registered User
    Join Date
    Jun 2008
    Posts
    161
    Quote Originally Posted by Salem View Post
    You've only got ONE UserSys, so the 2nd one will surely barf.
    Uh, "struct system_vars UserSys[1];" Doesn't that mean there's 2, since it starts at 0? Guess not. I changed it and things seem to work now.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Viper187 View Post
    Uh, "struct system_vars UserSys[1];" Doesn't that mean there's 2, since it starts at 0? Guess not. I changed it and things seem to work now.
    No, when you do
    Code:
    sometype array[n];
    you get n number of elements, which uses an index from 0..(n-1). So [1] means that you have ONE element, indexed 0.

    --
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Separate long string into multiple arrays
    By cashmerelc in forum C Programming
    Replies: 6
    Last Post: 11-27-2007, 02:57 AM
  2. One quick question...
    By Kross7 in forum C++ Programming
    Replies: 10
    Last Post: 04-13-2007, 09:50 PM
  3. Error message in tic tac toe problem please help
    By Kross7 in forum C++ Programming
    Replies: 17
    Last Post: 04-10-2007, 01:50 PM
  4. Massive Function Problem
    By Marc Sharp in forum C Programming
    Replies: 10
    Last Post: 11-19-2003, 08:49 PM
  5. Replies: 22
    Last Post: 11-08-2001, 11:01 PM