Teensy 4.0 crash with BigNumber variables

Status
Not open for further replies.

jacques

New member
Hey everyone,

I'm trying to port a measurement program from the Arduino Nano Every to Teensy 4.0. The program is using the BigNumber library (see: https://github.com/nickgammon/BigNumber); I've attached a copy of the library to this post.

Unfortunately, when trying to declare BigNumber variables as class members or global variables, the Teensy board seemingly crashes after uploading the code.

Here's a very basic program that reproduces the problem:

Code:
#include <BigNumber.h>

BigNumber testNum;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(100000);
}

void loop() 
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}

After uploading this code, the program never enters the loop method. When the BigNumber variable declaration is commented out, the built-in LED starts blinking as expected.

Note that the following does execute successfully (the LED starts blinking and when opening a serial monitor it is receiving the correct number):

Code:
#include <BigNumber.h>

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(100000);
  BigNumber::begin(16);
}

void loop() 
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);

  BigNumber testNum = BigNumber("1234567890.1234567890");
  Serial.println(testNum);
}

Any ideas as to what might be causing this? Or how I might be able to work around this issue? The BigNumber type is used extensively in the code that I'm porting, so it would be a pain to have to use a different library.

Cheers,

Jacques
 

Attachments

  • BigNumber.zip
    20.1 KB · Views: 47
You cannot create a BigNumber before calling BigNumber::begin(), otherwise the BigNumber constructor will dereference a null pointer and crash your program.

Pieter
 
You cannot create a BigNumber before calling BigNumber::begin(), otherwise the BigNumber constructor will dereference a null pointer and crash your program.

Ah, I see. Color me surprised that the Arduino didn't crash from such an egregious error.

What would then be a good way to make something like this work:

Header file:
Code:
#include <BigNumber.h>

class Foo
{
  private:
    static BigNumber bar;

  public:
    static BigNumber* getBarPtr();
};

Cpp file:
Code:
#include "Foo.h"

BigNumber Foo::bar;

BigNumber* Foo::getBarPtr()
{
  return &(Foo::bar);
}
 
Something like this, perhaps?
Code:
class Foo {
  public:
    static BigNumber* getBarPtr() {
        static BigNumber bar; // Costructed when this function is first called
        return &bar;
    }
};
Of course, you should only call this function after initializing the library, which might just move the problem to a different place in your code.

On an unrelated note, why return a pointer and not a reference? Pointers usually imply that they could be nullptr, and using references is less noisy.
 
Good point. I don't even recall what the reason was, but it would be cleaner to just return a reference.
 
I'm curious, is there any reason that the library shouldn't have an empty constructor and do the initialization in begin()? In any case, just crashing is poor design.
 
A quick glance at the source seems to reveal that the default constructor copies the contents of a pre-allocated “zero” constant BigNumber. This constant is created when calling BigNumber::begin(), so if you don't initialize it first, “zero” is still null, and it crashes.

I agree that it's poor design, it probably stems from the fact that the Arduino library is simply a C++ wrapper around a C library (which doesn't have constructors).
 
Status
Not open for further replies.
Back
Top