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