0

I am trying to use the new operator to create a global reference, by declaring tNMEA2000 &NMEA2000=*(new tNMEA2000_stm()); outside of any functions.

When I use tNMEA2000 &NMEA2000=*(new tNMEA2000_stm()); outside of any functions, it ends up getting set to a NULLPTR. If I declare it inside of a function, it works correctly.

This isn't the actual code, but a simplified version. I haven't included the actual class definitions

#include "nmea_wrapper.h" //This defines the tNMEA2000_stm class
#include "NMEA2000.h" //This defines the tNMEA2000 class that tNMEA2000_stm inherits from

tNMEA2000 &NMEA2000 = *(new tNMEA2000_stm()); //This ends up with a NULLPTR

void setup(){
  tNMEA2000 &NMEA2000 = *(new tNMEA2000_stm()); //This correctly initializes the memory
}

From what I can understand declaring it globally should work, and not get set to a NULLPTR. I am not sure if this is a quirk of using newlib, and I can't seem to find any documentation to tell me one way from the other if it's valid or not.

  • 2
    Why do you want `MNEA2000` to be a reference? In this situation I would either make it a pointer (if it is essential that the object is on the heap) or just a normal global variable in all other cases. – Johan Feb 01 '19 at 06:37
  • If new is failing it could be throwing an exception. Using try catch to get the exception info could help. – Kieran Feb 01 '19 at 06:45
  • @Kieran We're talking about bare-metal embedded systems here. Exceptions are almost always disabled in this case. – J_S Feb 01 '19 at 07:13
  • 1
    By writing a little program, I haven't been able to replicate a similar problem. If you have set up a situation in which some global object relies on `NMEA2000` being properly initialised previously, then you have a problem, as the order of initialisation of all globals is unspecified between compilation units (look up static initialisation fiasco). However, you haven't provided a [mcve] so all anyone can do is guess what your problem is. – Peter Feb 01 '19 at 07:13
  • @Jacek I don't deduce bare metal from this. However, of that is the case, 0x0000 could be a valid address. Looks like we need to be able to reproduce – JVApen Feb 01 '19 at 07:22
  • @JVApen 'stm32' is in the tags. `0x00000000` is not a valid memory address in context, as it either doesn't map to anything or maps to ROM / flash memory. – J_S Feb 01 '19 at 07:34
  • 1
    @Kieran: You can't have a try-catch block on the initializer of a global object. There's no call stack. – MSalters Feb 01 '19 at 08:05
  • @MSalters that’s a good point. Thanks. – Kieran Feb 01 '19 at 11:01
  • @Peter I think you may have actually hit the nail on the head! I am rather new to C++, and hadn't heard of the "static initialisation fiasco". I had made the assumption that things I had declared in a global scope would be initialized before the program started running. Using the "Construct On First Use Idiom" resolves the problem. I tried to package it down into an example that could be posted, but I couldn't recreate the issue in a something that didn't involve uploading half the project. – silverchris Feb 02 '19 at 01:33

0 Answers0