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

uVision Watch window does not like static ...

I use uVision 4.53 (with Armcc V4.1.0.894), processor STM32F407 with standard settings.

If I compile the following small program:

class Test{
public:
        static int i1;
        static int i2;

        int TestFunc( void);
};

int Test::TestFunc( void){
        i1= i2;
        return 0;
}

Test T;

int main( void){

        T.TestFunc();

        while( 1);
}

Then the watch window will show the class element T with the address "0x20000014 &T". This is a bit strange, as the address of i1 is 0x2000001C and address of i2 is 0x20000018 (as you can easily see if you look at the disassembly of the line "i1=i2" in function TestFunc).

If I try to change the value of T1.i1 in the watch window, it will fail - it always keeps zero, even after I enter some changed value.

The miracle happens, if I change the class definition to

class Test{
public:
        static int i1;
        static int i2;

        static int TestFunc( void);
};

Then the watch window will show the class element T with the address "0x00000000" (this usually would mean, that T is not used in the software - so this evidently is wrong). But nicely now i1 and i2 can be accessed without problems through the watch window.

I came to this problem through large classes with structs. For structs you clearly see the address in the watch window. There I recognized that the adresses sometimes were complete nonsense (it showed 0x4000000 adresses for normal variables - 0x4000000 is reserved for peripheral registers, so it is impossible).

It seems to be important, that all functions which are invoked from some static C-like funktion (as main()), need to be static. Otherwise the watch window does very strange things.

BTW: It would make a bit sense, if in the "Type" field uVision would show "class T" (now it says "struct T", which is slightly disturbing ...).

Parents
  • PS: The first example of this thread was compiled with the compiler switch --anachronisms. If you skip this, then you need to define the variables i1 and i2 separately again, as you showed in your example - you are right in this point. But this does not change the fact, that the watch window will NOT work, if you translate this "first post of this thread" example - also if you add the external definition of i1 and i2.

Reply
  • PS: The first example of this thread was compiled with the compiler switch --anachronisms. If you skip this, then you need to define the variables i1 and i2 separately again, as you showed in your example - you are right in this point. But this does not change the fact, that the watch window will NOT work, if you translate this "first post of this thread" example - also if you add the external definition of i1 and i2.

Children
  • Just checked your initial example, without initializing the
    static data members i1 and i2, the linker outputs an error message
    because of undefined symbols:

    linking...
    .\output\cpp_template.axf: Error: L6218E: Undefined symbol Test::i1 (referred from main.o).
    .\output\cpp_template.axf: Error: L6218E: Undefined symbol Test::i2 (referred from main.o).
    Target not created
    </pre/>
    
    After adding the static initializers as shown below, everything is fine -
    the value displays of i1 and i2 in the watch window are correct. Once more
    again, dragging such a symbol from the symbol window into the watch window
    is the easiest way to get correctly qualified symbols (instead of having to
    enter \\cpp_template\../../source/main.cpp\i1 or something similar).
    
    
    
    class Test  {
    public:
      static int i1;
      static int i2;
      int TestFunc( void);
    };
    
    int Test::TestFunc( void)  {
      i1 = i2;
      return 0;
    }
    
    Test T;
    int Test::i1 = 1;
    int Test::i2 = 2;
    
    int main1 (void)  {
      T.TestFunc();
      return (1);
    }
    ...
    <pre/>
    
    
    

  • I'm sorry for the bad formatting...

    Just checked your initial example, without initializing the
    static data members i1 and i2, the linker outputs an error message
    because of undefined symbols:

    linking...
    .\output\cpp_template.axf: Error: L6218E: Undefined symbol Test::i1 (referred from main.o).
    .\output\cpp_template.axf: Error: L6218E: Undefined symbol Test::i2 (referred from main.o).
    Target not created
    

    After adding the static initializers as shown below, everything is fine -
    the value displays of i1 and i2 in the watch window are correct. Once more
    again, dragging such a symbol from the symbol window into the watch window
    is the easiest way to get correctly qualified symbols (instead of having to
    enter \\cpp_template\../../source/main.cpp\i1 or something similar).

    class Test  {
    public:
      static int i1;
      static int i2;
      int TestFunc( void);
    };
    
    int Test::TestFunc( void)  {
      i1 = i2;
      return 0;
    }
    
    Test T;
    int Test::i1 = 1;
    int Test::i2 = 2;
    
    int main1 (void)  {
      T.TestFunc();
      return (1);
    }
    ...
    

  • Hi Gp F,
    I tried exactly your example, and it does NOT work.

    (but I renamed your "main1" to "main", and in main I replaced your "return (1);" by "while(1);").

    It shows T in the watch window (with address "0x20000014 &T"), and it is possible to enlarge T to see i1 and i2. But i1 and i2 somehow do not work - if I try to change the value of the variable i1 to e. g. "5", then it always flips back to zero (after pressing enter).

    If I change the declaration of "int TestFunc(void);" to "static int TestFunc(void);", then all works nicely (no problem to change the variable i1 in the watch window to any value I want).

    [ I am quite sure that the variable i1 in the watch window somehow has some completely wrong address (I met this problem in larger classes containing larger structs - there the struct address is always shown in the watch window, and the struct adresses shown there were in the 0x40000000 range, which is impossible for STM32F4 programs ...) ( Unfortunately it is not possible to see the address of i1 in the watch window ) (this would be a very nice additional feature in the watch window: Showing an additional column with the address, and if you would consider to create additional columns, perhaps also another column with decimal/float value (perhaps possible to switch on/off with right mouse key - in larger projects sometimes it is very useful, if you can watch your data as well in hex as in decimal or float)) ]

    To rule out, that it is a problem with my hardware (ST4Discovery, new ST-Link Debugger which came with uVision 4.53), I tried also in simulation mode, but there I come to the same problem. So it should be no problem for you, to duplicate the problem on your system.