arduino / Arduino

Arduino IDE 1.x
https://www.arduino.cc/en/software
Other
14.16k stars 7.02k forks source link

Variable optimised away if declared in external .cpp (ESP8266) #8835

Closed philbowles closed 5 years ago

philbowles commented 5 years ago

I hope this isn't an ESP8266 issue: I will post it there too just in case.

Symptom is that working code fails (panic + stack dump) if definition of static std::function is moved to .cpp file. Most of the rest is beyond my pay grade but it seems maybe the variable has been "optimised away"

Arduino IDE 1.8.9 + ESP8266 core 2.4.0 (I know it's not the latest but 2.50. adds 35k+ of additional bloat that breaks OTA on my big projects... :( )

The Code:

Its MVCE, cut out of a 5000+ line project. The workaround "solution" of having the code in the same file where its called is just not viable. Class .h file

#ifndef FUNCSPOOL_H
#define FUNCSPOOL_H

#include<Arduino.h>
#include <string>
#include <functional>

using namespace std;

class funcSpool{     
      function<void(string)>    fail;
  protected:
      static  function<void(string)>   staticFail;
  public:
            funcSpool(function<void(string)> f=staticFail): fail(f){} 
    virtual ~funcSpool(){}             
      void  run(const string s){ fail(s); }     
};
class fsPassthru: public funcSpool{};
#endif // funcspool_H

the external .cpp file

#include "funcSpool.h"
//When uncommented and thus declared in .cpp file, panic results
function<void(string)> funcSpool::staticFail  =[](string s){ Serial.printf("STATIC FUNCTOR %s\n",s.c_str()); };

The main .ino:

#include "funcSpool.h"
//When uncommented and thus declared HERE, all is correct
//function<void(string)> funcSpool::staticFail  =[](string s){ Serial.printf("STATIC FUNCTOR %s\n",s.c_str()); };

funcSpool*  gsp=new fsPassthru;

void setup() {
  Serial.begin(74880);
  string test="always works locally both ways";

  funcSpool*  lsp=new fsPassthru;
  Serial.printf("LOCAL POINTER %08x\n",(void*)lsp); 
  lsp->run(test);

  Serial.printf("GLOBAL POINTER %08x\n",(void*)gsp); 
  gsp->run(test);
  Serial.printf("EVERYTHING OK\n");
}

void loop(){}

The working output:

From the "correct" run where funcSpool::staticFail is declared within the .ino by uncommenting Includes portions of the .map file

LOCAL POINTER 3ffef5c4
STATIC FUNCTOR always works locally both ways
GLOBAL POINTER 3ffef434
STATIC FUNCTOR always works locally both ways
EVERYTHING OK

Map

.literal.setup
                0x00000000        0x0 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcspool3.ino.cpp.o
 .literal.startup._GLOBAL__sub_I__ZN9funcSpool10staticFailE
                0x00000000        0x0 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcspool3.ino.cpp.o
 .literal.exit._GLOBAL__sub_D__ZN9funcSpool10staticFailE
                0x00000000        0x0 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcspool3.ino.cpp.o
...
.text.startup._GLOBAL__sub_I__ZN9funcSpool10staticFailE
                0x40202698       0x40 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcspool3.ino.cpp.o
                                 0x5c (size before relaxing)
 .text.exit._GLOBAL__sub_D__ZN9funcSpool10staticFailE
                0x402026d8       0x15 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcspool3.ino.cpp.o
                                 0x1d (size before relaxing)
 *fill*         0x402026ed        0x3
 ...
  .bss._ZN9funcSpool10staticFailE
                0x3ffee84c       0x10 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcspool3.ino.cpp.o
                0x3ffee84c                funcSpool::staticFail

The Failing Output:

The .ino declaration is commented out and the .cpp declaration is uncommented:

LOCAL POINTER 3ffef5b4
STATIC FUNCTOR always works locally both ways
GLOBAL POINTER 3ffef42c

Panic C:\Users\phil\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.2\cores\esp8266\abi.cpp:106 __throw_bad_function_call

ctx: cont 
sp: 3ffffd50 end: 3fffffd0 offset: 01b0

>>>stack>>>
3fffff00:  424f4c47 50204c41 544e494f 33205245  
3fffff10:  66656666 0a633234 3ffef500 00000017  
3fffff20:  6000001c 00000017 000000f3 4010020c  
3fffff30:  3ffe8860 3ffef5b4 3fffff10 40208f8e  
3fffff40:  3fffff80 3fffff50 00000008 3ffee89c  
3fffff50:  3fffdad0 3ffef5b4 3ffef42c 40209028  
3fffff60:  6000001c 0000002e 3ffef5b4 40202a89  
3fffff70:  3ffe88a8 00000000 3ffef42c 402025ea  
3fffff80:  3ffeece4 3ffef590 402024d0 3ffee89c  
3fffff90:  3fffdad0 3ffee858 3ffee878 402026c7  
3fffffa0:  3ffef590 3ffef590 feefeffe feefeffe  
3fffffb0:  feefeffe 00000000 3ffee894 40202bc0  
3fffffc0:  feefeffe feefeffe 3ffe84fc 40100739  
<<<stack<<<

Decoding 9 results
0x4010020c: _umm_free at C:\Users\phil\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.2\cores\esp8266\umm_malloc/umm_malloc.c line 1295
0x40208f8e: std::basic_string  , std::allocator  >::~basic_string() at /Users/igrokhotkov/e/ESPTools/crosstool-NG/.build/xtensa-lx106-elf/build/build-cc-gcc-final/xtensa-lx106-elf/libstdc++-v3/include/bits/basic_string.h line 2208
0x40209028: std::basic_string  , std::allocator  >::basic_string(std::string const&) at /Users/igrokhotkov/e/ESPTools/crosstool-NG/.build/xtensa-lx106-elf/build/build-cc-gcc-final/xtensa-lx106-elf/libstdc++-v3/include/bits/basic_string.h line 2208
0x40202a89: std::__throw_bad_function_call() at ?? line ?
0x402025ea: _Alloc_hider at c:\users\phil\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits/basic_string.h line 272
:  (inlined by) basic_string at c:\users\phil\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits/basic_string.h line 508
:  (inlined by) std::function ::operator()(std::string) const at c:\users\phil\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2/functional line 2464
:  (inlined by) funcSpool::run(std::string) at C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch/funcSpool.h line 17
0x402024d0: _M_manager at c:\users\phil\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2/functional line 1931
0x402026c7: setup at C:\Users\phil\Desktop\funcspool 3\funcspool3/funcspool3.ino line 16
0x40202bc0: loop_wrapper at C:\Users\phil\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.2\cores\esp8266/core_esp8266_main.cpp line 122
0x40100739: cont_wrapper at C:\Users\phil\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.4.2\cores\esp8266/cont.S line 81

Discarded input sections

 .group         0x00000000       0x10 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcSpool.cpp.o
 .literal._ZNSt17_Function_handlerIFvSsEN9funcSpoolUlSsE_EE9_M_invokeERKSt9_Any_dataSs
                0x00000000        0x0 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcSpool.cpp.o
 .literal._ZNSt14_Function_base13_Base_managerIN9funcSpoolUlSsE_EE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation
                0x00000000        0x0 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcSpool.cpp.o
 .literal.startup._GLOBAL__sub_I__ZN9funcSpool10staticFailE
                0x00000000        0x0 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcSpool.cpp.o
 .literal.exit._GLOBAL__sub_D__ZN9funcSpool10staticFailE
                0x00000000        0x0 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcSpool.cpp.o
...
 .text.startup._GLOBAL__sub_I__ZN9funcSpool10staticFailE
                0x40202508       0x37 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcSpool.cpp.o
                                 0x3b (size before relaxing)
 *fill*         0x4020253f        0x1 
 .text.exit._GLOBAL__sub_D__ZN9funcSpool10staticFailE
                0x40202540       0x15 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcSpool.cpp.o
                                 0x1d (size before relaxing)
 *fill*         0x40202555        0x3 
...
.bss._ZN9funcSpool10staticFailE
                0x3ffee848       0x10 C:\Users\phil\AppData\Local\Temp\arduino_build_321602\sketch\funcSpool.cpp.o
                0x3ffee848                funcSpool::staticFail
philbowles commented 5 years ago

UPDATE: just downloaded core 2.5.0 - behaviour is identical

matthijskooijman commented 5 years ago

This was diagnosed in the related esp8266 issue https://github.com/esp8266/Arduino/issues/6032, so I'm closing this one.