What else is consuming Data Segment reported by avr-size? I am facing a low memory available problem in arduino. I am compiling a big sketch for arduino mega 2560.
Analysing a .elf file, the avr-size tool gives:
text    data     bss     dec     hex filename
68524   4392    2560   75476   126d4 C:\Users\LEAN...

And the avr-nm (avr-nm doc) shows only variables with t, T, b, d and B. The following is how the command is executed (the output is being saved in a file called test.txt).
   avr-nm -a -td -C -l --size-sort -r x.elf &gt;&gt; test.txt

Then, I perform a sum to confirm the avr-size result using this Python script:
f = open(&quot;test.txt&quot;, &quot;r&quot;)
lines = f.readlines()
f.close()

su = 0
dsum = 0
bsum = 0
tsum = 0
gsum = 0
for line in lines:
    #print(line, end=&quot;&quot;)
    s = line.split()
    try:
        val = int(s[0])
        su = su + val
        if(s[1].lower() == 'b'):
            bsum = bsum + val
        if(s[1].lower() == 'd'):
            print(line)
            dsum = dsum + val
        if(s[1].lower() == 't'):
            tsum = tsum + val
        if(s[1].lower() == 'g'):
            gsum = gsum + val
    except:
        print(&quot;ERR: &quot;,s[0])
print(&quot;\n\nSIZE: &quot;, su)
print(&quot;SIZE d/D: &quot;, dsum)
print(&quot;SIZE b/B: &quot;, bsum)
print(&quot;SIZE t/T: &quot;, tsum)
print(&quot;SIZE g/G: &quot;, gsum)

and the sum result of each var type is:
SIZE:  71015
SIZE d/D:  135
SIZE b/B:  2560
SIZE t/T:  68320
SIZE g/G:  0

The question: Here d/D sums is 135 bytes. So, why the data segment reported by avr-size is 4392 bytes? how to find out what is occupying this space?
Best Regards.
EDIT
It must be a Joke!
I have a lot of like this in the code:
Serial.print(&quot;QTDE REG: &quot;);

Just changing for this:
Serial.print(F(&quot;QTDE REG: &quot;));

I have reduced by 10 the .data size!
So, in this way Serial.print(&quot;QTDE REG: &quot;); &quot;QTDE REG: &quot; is stored as a global variable?? I thought the compiler would save locally.
EDIT 2
I have an advance running avr-objdump -s -j .data x.elf as suggested by Edgar below. Now I see that all my string literals are in data! For example:
void myFunction(){
    ...
    sprintf(buf, &quot;{\&quot;name\&quot;:\&quot;Intervalo de Registros\&quot;,\&quot;value\&quot;:\&quot;%d\&quot;, \&quot;unit\&quot;:\&quot;C\&quot;},&quot;, (int)settings.treg);
    ...
}

avr-objdump -s -j .data x.elf shows:
 800660 2c007b22 6e616d65 223a2249 6e746572  ,.{&quot;name&quot;:&quot;Inter
 800670 76616c6f 20646520 52656769 7374726f  valo de Registro
 800680 73222c22 76616c75 65223a22 2564222c  s&quot;,&quot;value&quot;:&quot;%d&quot;,
 800690 2022756e 6974223a 2243227d 2c007b22   &quot;unit&quot;:&quot;C&quot;},.{&quot;

EDIT 3
As commented, all string literals are saved in the (SRAM). So, the problem is, I have a lot of strings literals spread across different functions. How to save this amount of SRAM? Note that using F() for sprintf gives compilation error.
Is there any way to put the literal in stack (release memory when function returns) and not in the global area? Is F() the only solution?
============ SOLUTION ============
For now, I have found this solution: use sprintf_P with PSTR(...) in the same way of F(...):
sprintf_P(buf, PSTR(&quot;{\&quot;name\&quot;:\&quot;Intervalo de Registros\&quot;,\&quot;value\&quot;:\&quot;%d\&quot;, \&quot;unit\&quot;:\&quot;C\&quot;},&quot;), (int)settings.treg);

I will test more...
Thanks for all clarification!
Best Regards!
Most of the missing data section is probably made of string literals.
When you write something like
Serial.println(&quot;Hello, World!&quot;);

the string &quot;Hello, World!&quot; is implemented by the compiler as an
anonymous array of characters, and the address of this array is
provided to the println() method. Since the array is anonymous, it
doesn't show up in the output of avr-nm. You can check that this is
the case by looking at the actual contents of the section:
avr-objdump -s -j .data x.elf

And you can avoid this by wrapping the strings in the F() macro:
Serial.println(F(&quot;Hello, World!&quot;));

This has the effect of keeping the string in flash, and passing the
flash address to the println() method. Note that this is actually a
different, overloaded method, that knows how to retrieve the character
data from flash.

Edit: Adding some clarifications.
All this complexity about flash vs. RAM storage comes from the fact that
the AVR uses a Harvard architecture, where RAM and flash are
in different address spaces, accessed through different memory buses
using different machine instructions. Unlike C, the C++
language has no notion of address spaces, and the compiler simply
assumes that any pointer to function holds a flash address, whereas any
pointer to data holds a RAM address.
Per the rules of the language, a string literal has the type
const char *, and a function that should be able to accept a string
literal should take a const char * parameter. Since these are pointers
to data, when you dereference them the compiler emits the machine
instructions that are appropriate for reading RAM. This is why the
compiler puts all string literals in the .data section of the flash: at
program startup, the C runtime copies them to the .data section of the
RAM, making them accessible to those machine instructions.
The current solution to avoid this useless copy involves a bunch of
preprocessor macros like F(), PSTR(), PROGMEM,
pgm_read_byte()... that expand to compiler extensions or inline
assembly. These allow you to pass around the flash addresses of string
literals disguised as regular data pointers. These pointers should never
be dereferenced with the regular operators of the language (* and
[]), but only through the pgm_read_*() macros. And they should only
be given to functions that do expect these kind of pointers, like
sprintf_P() or Print::println(const __FlashStringHelper *), which is
the println() that gets invoked when using the F() macro.

Is there any way to put the literal in stack

Yes, there is, but it has to be done explicitly:
PROGMEM const char greeting[] = &quot;Hello, World!&quot;;

void say_hello() {
    char stack_copy[strlen_P(greeting)+1];
    strcpy_P(stack_copy, greeting);
    Serial.println(stack_copy);
}

As you have already noticed, it is preferable to not put the strings in
RAM at all, and instead use functions like sprintf_P that expect
flash-based strings. However, if you need to use a library function that
expects a RAM-based string, you can use this trick to avoid permanently
committing it to RAM.