C++ global variables can't be watched in AVR Studio

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If I declare a global variable in C++ with GCC, the AVR Studio debugger will not recognize it. If I try to set a watch on the variable, it simply says "out of scope". I tried throwing extern "C" on it in case it was a name decoration issue, but that didn't help.

Local variables, including local static variables, are recognized OK. If compiled as C instead of C++, it also works fine.

I've had this problem with all versions of AVR Studio & WinAVR I've used, including the latest. Is this a known bug, and is there a work-around?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Try making the variable 'volatile' so it is not optimised into register only usage.

(alternatively build the code -O0 but this is not a great solution!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

These variables are not being optimized into registers. I can look at the code or the map file and find the corresponding memory to watch. Some of them are buffers and some have values shared between interrupt service routines.

Take the following example:

#include 

volatile int global;

int main()
{
	for (;;)
	{
		global++;
		if (global & 1)
			PINB |= 1;
	}
}

If compiled as C, the variable global can be watched fine. If you add the command-line switch "-x c++", watching global returns only "Not in scope".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And what does the compiled code (either in the .s file or the .lss file) look like?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The resulting code is exactly the same for either compiler:

int main()
  ce:	80 91 00 01 	lds	r24, 0x0100
  d2:	90 91 01 01 	lds	r25, 0x0101
  d6:	01 96       	adiw	r24, 0x01	; 1
  d8:	90 93 01 01 	sts	0x0101, r25
  dc:	80 93 00 01 	sts	0x0100, r24
{
	for (;;)
	{
		global++;
		if (global & 1)
  e0:	80 91 00 01 	lds	r24, 0x0100
  e4:	90 91 01 01 	lds	r25, 0x0101
  e8:	80 ff       	sbrs	r24, 0
  ea:	f1 cf       	rjmp	.-30     	; 0xce 
PINB |= 1; ec: b0 9a sbi 0x16, 0 ; 22 ee: ef cf rjmp .-34 ; 0xce

The debugging information is a little different, but I don't know how to make sense of it. I guess the problem could just as easily be in the compiler as in the debugger.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does seem to be some difference in debug symbol generation between the two compilers. If you build the two .elf variants then use avr-readelf -a on them and compare the output the only real area of difference is (C version):

  [ 7] .debug_info       PROGBITS        00000000 00055b 00008e 00      0   0  1
  [ 8] .debug_abbrev     PROGBITS        00000000 0005e9 000057 00      0   0  1
  [ 9] .debug_line       PROGBITS        00000000 000640 0000b3 00      0   0  1
  [10] .debug_frame      PROGBITS        00000000 0006f4 000020 00      0   0  4
  [11] .debug_str        PROGBITS        00000000 000714 000077 01  MS  0   0  1
  [12] .shstrtab         STRTAB          00000000 00078b 000092 00      0   0  1
  [13] .symtab           SYMTAB          00000000 000a78 0004b0 10     14  27  4
  [14] .strtab           STRTAB          00000000 000f28 0002ef 00      0   0  1

(C++ version):

  [ 7] .debug_info       PROGBITS        00000000 00055b 00009f 00      0   0  1
  [ 8] .debug_abbrev     PROGBITS        00000000 0005fa 00006d 00      0   0  1
  [ 9] .debug_line       PROGBITS        00000000 000667 0000c1 00      0   0  1
  [10] .debug_frame      PROGBITS        00000000 000728 000020 00      0   0  4
  [11] .debug_str        PROGBITS        00000000 000748 000079 01  MS  0   0  1
  [12] .shstrtab         STRTAB          00000000 0007c1 000092 00      0   0  1
  [13] .symtab           SYMTAB          00000000 000aac 0004b0 10     14  27  4
  [14] .strtab           STRTAB          00000000 000f5c 0002ef 00      0   0  1

It's the sizes on debug_info, debug_abbrev, debug_line and debug_str that differ.

Not sure if this is highlighting a fault in Studio's ability to parse the ELF file or the C++ compiler's ability to generate it correctly in the first place.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually comparing the outputs of avr-readelf --debug-dump is possibly even more telling if you search for "global". The C variant has:

 <1><75>: Abbrev Number: 5 (DW_TAG_variable)
     DW_AT_name        : (indirect string, offset: 0x2c): global	
     DW_AT_decl_file   : 3	
     DW_AT_decl_line   : 334	
     DW_AT_type        : <88>	
     DW_AT_external    : 1	
     DW_AT_location    : 5 byte block: 3 60 0 80 0 	(DW_OP_addr: 800060)

while the C++ variant has:

 <1><75>: Abbrev Number: 5 (DW_TAG_namespace)
     DW_AT_sibling     : <8e>	
     DW_AT_name        : ::	
     DW_AT_decl_file   : 4	
     DW_AT_decl_line   : 0	
 <2><7f>: Abbrev Number: 6 (DW_TAG_variable)
     DW_AT_name        : (indirect string, offset: 0xe): global	
     DW_AT_decl_file   : 3	
     DW_AT_decl_line   : 334	
     DW_AT_type        : <8e>	
     DW_AT_external    : 1	
     DW_AT_declaration : 1	

I wonder if what's being seen is anything to do with that additional "DW_TAG_namespace" before the "global" entry ?

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had seen the namespace entry in the debug info so I tried watching "::global" but it didn't help.