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
  • Given the example below with some static's, it is of course
    possible to have the static members being shown in the watch
    window. It is a matter of symbol qualification.

    Open the symbol window, then expand the module where your class is
    defined - then a careful look might help to see how the compiler
    lowers the static members.

    Anyway, drag the static symbol into a watch window - it will be
    there with the correct value being shown.

    You might also drag such a symbol into the command window,
    this shows the fully qualified symbol. By right clicking
    a variable in the symbol window, adding a symbol to a watch
    or memory or expanding the the qualification can be done as
    well.

    class CX1  {
      static  int    si1, si2;
    
    public:
      CX1();
      ...
    };
    
    int CX1::si1 = -10;  // static initializer
    int CX2::si2 = +10;  // static initializer
    

Reply
  • Given the example below with some static's, it is of course
    possible to have the static members being shown in the watch
    window. It is a matter of symbol qualification.

    Open the symbol window, then expand the module where your class is
    defined - then a careful look might help to see how the compiler
    lowers the static members.

    Anyway, drag the static symbol into a watch window - it will be
    there with the correct value being shown.

    You might also drag such a symbol into the command window,
    this shows the fully qualified symbol. By right clicking
    a variable in the symbol window, adding a symbol to a watch
    or memory or expanding the the qualification can be done as
    well.

    class CX1  {
      static  int    si1, si2;
    
    public:
      CX1();
      ...
    };
    
    int CX1::si1 = -10;  // static initializer
    int CX2::si2 = +10;  // static initializer
    

Children
  • With the program example which I gave you in the first post of this thread, it definitely will NOT work.

    I came through it, because I recognized that in some of my classes in a larger project I was not able to watch some of the member variables. Looking into this problem quite I while, I came to this stripped example of my first thread - please just copy it in some main.cpp and compile yourself and you should see it. (You might take the blinky of some STM32F4 example, and just replace the main.cpp).

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

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