This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

for(N = List->Head;N;N = N->Succ)

struct NODE{
    struct NODE Succ;
    struct NODE Prev;
};

struct LIST{
    struct NODE *Head;
    struct NODE *Tail;
    int count;
};

struct LIST *List;
struct NODE *N;

......
for(N = List->Head;N;N = N->Succ)
{
    ......
}
Compiler C51 changed value of List->Head because of the side effect of N = N->Succ.What can I do?

Parents
  • I have tried your code with some init statements and could not find out, that the list items ((Head/Tail) get changed after loop execution - the compiler works properly.

    Maybe you have some other additional code that changes the structure elements.

    struct NODE{
        struct NODE *Succ;
        struct NODE *Prev;
    };
    
    struct LIST{
        struct NODE *Head;
        struct NODE *Tail;
        int count;
    };
    
    
    struct LIST MyList;
    struct NODE FirstNode;
    struct NODE SecondNode;
    
    
    main()
    {
    	struct LIST *List;
    	struct NODE *N;
    
    	// init nodes and list
    	FirstNode.Succ = &SecondNode;
    	FirstNode.Prev = 0;
    	SecondNode.Succ = 0;
    	SecondNode.Prev = &FirstNode;
    	MyList.Head = &FirstNode;
    	MyList.Tail = &SecondNode;
    	MyList.count = 2;
    
    	List = &MyList;
    
    	// loop over all nodes
    	for(N = List->Head;N;N = N->Succ)
    	{
    	}
    
    }
    

Reply
  • I have tried your code with some init statements and could not find out, that the list items ((Head/Tail) get changed after loop execution - the compiler works properly.

    Maybe you have some other additional code that changes the structure elements.

    struct NODE{
        struct NODE *Succ;
        struct NODE *Prev;
    };
    
    struct LIST{
        struct NODE *Head;
        struct NODE *Tail;
        int count;
    };
    
    
    struct LIST MyList;
    struct NODE FirstNode;
    struct NODE SecondNode;
    
    
    main()
    {
    	struct LIST *List;
    	struct NODE *N;
    
    	// init nodes and list
    	FirstNode.Succ = &SecondNode;
    	FirstNode.Prev = 0;
    	SecondNode.Succ = 0;
    	SecondNode.Prev = &FirstNode;
    	MyList.Head = &FirstNode;
    	MyList.Tail = &SecondNode;
    	MyList.count = 2;
    
    	List = &MyList;
    
    	// loop over all nodes
    	for(N = List->Head;N;N = N->Succ)
    	{
    	}
    
    }
    

Children
  • I found that N and List is located in the same memory address(D:0x01) because List is no longer used after

    N = List->Head
    
    My C51 version is 7.06 and used default optimization level(8).So if I used optimization level 0 or use List after the for loop body,such as
    List-Head = (void*)0;
    
    N and List is located in different memeory space.

  • Have you checked the memory address in the map-file??

    I tried different settings (SMALL/LARGE memory model, Optimization level 0 and 8, Linker LX51/BL51,...) but N and List were NEVER located on the same memory address !!!!!

  • I tried two different settings (using optimization level 0 and 8)under Large Memory Model,When using level 8,N and List were located in the same memory address,but when level 0,they weren't.
    Level 8:

    SYMBOL TABLE OF MODULE:  test (MAIN)
    
          VALUE       REP       CLASS    TYPE      SYMBOL NAME
          ====================================================
          ---         MODULE    ---      ---       MAIN
          0200000EH   PUBLIC    XDATA    ---       SecondNode
          02000006H   PUBLIC    XDATA    ---       MyList
          02000000H   PUBLIC    XDATA    ---       FirstNode
          01000003H   PUBLIC    CODE     ---       main
    
          01000003H   BLOCK     CODE     ---       LVL=0
          00000001H   SYMBOL    DATA     ---       List
          00000001H   SYMBOL    DATA     ---       N
          ---         BLOCKEND  ---      ---       LVL=0
    
    Level 0:
    SYMBOL TABLE OF MODULE:  test (MAIN)
    
          VALUE       REP       CLASS    TYPE      SYMBOL NAME
          ====================================================
          ---         MODULE    ---      ---       MAIN
          0200000EH   PUBLIC    XDATA    ---       SecondNode
          02000006H   PUBLIC    XDATA    ---       MyList
          02000000H   PUBLIC    XDATA    ---       FirstNode
          01000003H   PUBLIC    CODE     ---       main
    
          01000003H   BLOCK     CODE     ---       LVL=0
          02000014H   SYMBOL    XDATA    ---       List
          02000017H   SYMBOL    XDATA    ---       N
          ---         BLOCKEND  ---      ---       LVL=0
    

  • Ok, I stripped down the code: optimization level 8, large (code/data), generic 8051 device

    struct NODE{
        struct NODE *Succ;
        struct NODE *Prev;
    };
    
    struct LIST{
        struct NODE *Head;
        struct NODE *Tail;
        int count;
    };
    
    main()
    {
        struct LIST *List;
        struct NODE *N;
    
        // loop over all nodes
        for(N = List->Head;N;N = N->Succ)
        {
        }
    }
    
    -> MAP file (looks a bit different to yours): List and N are on different memory locations.
          VALUE       REP       CLASS    TYPE      SYMBOL NAME
          ====================================================
          ---         MODULE    ---      ---       MAIN
          0100004AH   PUBLIC    CODE     ---       main
    
          0100004AH   BLOCK     CODE     ---       LVL=0
          0100004AH   BLOCK     CODE     NEAR LAB  LVL=1
          02000000H   SYMBOL    XDATA    ---       List
          00000001H   SYMBOL    DATA     ---       N
          ---         BLOCKEND  ---      ---       LVL=1
          ---         BLOCKEND  ---      ---       LVL=0
    
    Why does your main() start at C:0x0003?

  • I'm baffled as to why "List" seems to be being placed in xdata in your map file.

    If I compile this code in the small memory model, all variables are placed in DATA. List and N are placed at the same address, however I think this is because N is never used in the code hence it doesn't matter where it is placed:

    struct NODE{
    struct NODE *Succ;
    struct NODE *Prev;
    };

    struct LIST{
    struct NODE *Head;
    struct NODE *Tail;
    int count;
    };

    struct LIST MyList;
    struct NODE FirstNode;
    struct NODE SecondNode;

    main()
    {
    struct LIST *List;
    struct NODE *N;

    // init nodes and list
    FirstNode.Succ = &SecondNode;
    FirstNode.Prev = 0;
    SecondNode.Succ = 0;
    SecondNode.Prev = &FirstNode;
    MyList.Head = &FirstNode;
    MyList.Tail = &SecondNode;
    MyList.count = 2;

    List = &MyList;

    // loop over all nodes
    for(N = List->Head;N;N = N->Succ)
    {
    }

    }

    VALUE REP CLASS TYPE SYMBOL NAME
    ====================================================
    --- MODULE --- --- JUNK
    00000016H PUBLIC DATA --- SecondNode
    00000010H PUBLIC DATA --- FirstNode
    00000008H PUBLIC DATA --- MyList
    01000003H PUBLIC CODE --- main

    01000003H BLOCK CODE --- LVL=0
    00000001H SYMBOL DATA --- List
    00000001H SYMBOL DATA --- N
    01000003H LINE CODE --- #44
    01000003H LINE CODE --- #45
    01000003H LINE CODE --- #50
    0100000CH LINE CODE --- #51
    01000015H LINE CODE --- #52
    0100001EH LINE CODE --- #53
    01000027H LINE CODE --- #54
    01000030H LINE CODE --- #55
    01000039H LINE CODE --- #56
    0100003FH LINE CODE --- #58
    01000045H LINE CODE --- #61
    0100004BH LINE CODE --- #62
    0100004BH LINE CODE --- #63
    0100004FH LINE CODE --- #65
    --- BLOCKEND --- --- LVL=0


    However, if I initialise N:

    struct NODE{
    struct NODE *Succ;
    struct NODE *Prev;
    };

    struct LIST{
    struct NODE *Head;
    struct NODE *Tail;
    int count;
    };

    struct LIST MyList;
    struct NODE FirstNode;
    struct NODE SecondNode;

    main()
    {
    struct LIST *List;
    struct NODE *N;

    // init nodes and list
    FirstNode.Succ = &SecondNode;
    FirstNode.Prev = 0;
    SecondNode.Succ = 0;
    SecondNode.Prev = &FirstNode;
    MyList.Head = &FirstNode;
    MyList.Tail = &SecondNode;
    MyList.count = 2;

    List = &MyList;
    N=&FirstNode;
    // loop over all nodes
    for(N = List->Head;N;N = N->Succ)
    {
    }

    }

    VALUE REP CLASS TYPE SYMBOL NAME
    ====================================================
    --- MODULE --- --- JUNK
    00000016H PUBLIC DATA --- SecondNode
    00000010H PUBLIC DATA --- FirstNode
    00000008H PUBLIC DATA --- MyList
    01000003H PUBLIC CODE --- main

    01000003H BLOCK CODE --- LVL=0
    0000001CH SYMBOL DATA --- List
    00000001H SYMBOL DATA --- N
    01000003H LINE CODE --- #44
    01000003H LINE CODE --- #45
    01000003H LINE CODE --- #50
    0100000CH LINE CODE --- #51
    01000015H LINE CODE --- #52
    0100001EH LINE CODE --- #53
    01000027H LINE CODE --- #54
    01000030H LINE CODE --- #55
    01000039H LINE CODE --- #56
    0100003FH LINE CODE --- #58
    01000048H LINE CODE --- #59
    01000048H LINE CODE --- #61
    01000054H LINE CODE --- #62
    01000054H LINE CODE --- #63
    01000058H LINE CODE --- #65
    --- BLOCKEND --- --- LVL=0

    Stefan

  • List is placed in XDATA because I use the large memory model (see message)...

    "N is never used in the code hence it doesn't matter where it is placed:
    "

    N is used in code: "N = List->Head" and "N = N->Succ" in the for-loop.

    In small model I get the following map-file:

          VALUE       REP       CLASS    TYPE      SYMBOL NAME
          ====================================================
          ---         MODULE    ---      ---       MAIN
          01000003H   PUBLIC    CODE     ---       main
    
          01000003H   BLOCK     CODE     ---       LVL=0
          01000003H   BLOCK     CODE     NEAR LAB  LVL=1
          00000008H   SYMBOL    DATA     ---       List
          00000001H   SYMBOL    DATA     ---       N
          ---         BLOCKEND  ---      ---       LVL=1
          ---         BLOCKEND  ---      ---       LVL=0
    
    N and List are still on different locations! The compiler generates code for the for-loop (optimization level 8!)

    Maybe a compiler/linker version problem?

    My versions are:
    C51: V7.06
    LX51: V3.58d
    (AX51: V2.09)

  • You were looking for the wrong kind of symptoms, then.

    The fact that two variables end up being placed in the same address, all by itself, tells you exactly nothing about the actual behaviour of the program. The compiler is perfectly allowed to re-use the memory positions used for 'List' to store something else in it after 'List' itself is no longer used. That's what the word "optimization" in "optimization level 8" is mainly about, after all.

    Without this kind of tricks, it would be close to impossible to fit any decent-sized C program into a typical 8051 device --- there simply isn't enough memory space to spare.

  • "List is placed in XDATA because I use the large memory model"

    Ok, but shouldn't N therefore be placed in xdata as well? Quoting from your map file above:

    02000000H SYMBOL XDATA --- List
    00000001H SYMBOL DATA --- N

    "N is used in code: "N = List->Head" and "N = N->Succ" in the for-loop"

    Yes, I must have been sleeping. Again.

    I think Hans is right, the optimisation is legitimately causing this. The order of events is (pseudocode):

    List=An address;
    N=List->Head;
    LABEL:
    N=N->Succ;
    if(N) goto LABEL

    So, List and N can occupy the same location without anything going wrong.

    Stefan