0

I have written my own 'assert' since I want to use it for both Windows and Arduino. The class is called from many files (about 10).

AssertUtils.h:

#pragma once

#define assert(expr) AssertUtils::Assert2((expr), (__func__), (__FILE__), (__LINE__));

class AssertUtils
{
public:
    static void Assert2(bool expression, const char* funcName, const char* fileName, int line);
};

AssertUtils.cpp:

#include "AssertUtils.h"
#include "Arduino.h"

/* static */ void AssertUtils::Assert2(bool expression, const char* funcName, const char* fileName, int line)
{
    if (!expression)
    {
        Serial.println(funcName);
        Serial.println(fileName);
        Serial.println(line, DEC);
        Serial.flush();

        // Abort program execution.
        abort();
    }
}

When I compile this, the SRAM usage is 1469 bytes (together with the rest of my sketch and classes).

When I comment the line below, I get a segmentation fault in a random assert call (when I comment out that call, I get it in the next, etc.).

    //Serial.println(funcName);

When I also comment out the second print statement, the compiler reports only 1137 bytes SRAM usage (which I expect since this was about equal until before I added the Assert class).

    //Serial.println(funcName);
    //Serial.println(fileName);

Questions:

  1. How can I get rid of the segmentation fault?
  2. How can it be that about 332 bytes are used for one two additional print statements? (maybe related to the const char* buffering (?)
8
  • 1
    the segmentation fault is a bug in compiler in 1.6.22 and 1.6.23. more here forum.arduino.cc/index.php?topic=619213.msg4195749#msg4195749
    – Juraj
    Commented Jun 2, 2019 at 16:00
  • 1
    try F(__FILE__) and F(__func__). (change the parameter type to __FlashStringHelper)
    – Juraj
    Commented Jun 2, 2019 at 16:03
  • 1
    @Juraj Somehow it only works for __FILE__ but not for __func__. Anyway using F( __FILE__) was about -90B difference (It's probably full path and it was only used in one file).
    – KIIV
    Commented Jun 2, 2019 at 16:32
  • 1
    so the compiler optimizes the parameters away if hey are not used
    – Juraj
    Commented Jun 2, 2019 at 17:49
  • 1
    Why are you wasting a class on this? Just use the prints directly in the macro.
    – Majenko
    Commented Jun 2, 2019 at 18:48

1 Answer 1

2

Note, this answer is not MY answer, but approximately the combination of the first 5 comments from my original question.

What I did was:

  • (Juraj) Changed the compiler version to 6.21
  • (juraj) Added an F in F(__FILE__)
  • (KIIV) Removed func; this did not work with the F flash helper, but I can find back the code anyway unambiguously because of the file name + line number.
  • (Majenko) I removed the class and use a macro. This costs some more Flash memory (depending on the number of asserts I use, but I'm still around 40% (was 35%).

The SRAM usage is now 1125 bytes, even less than where I'm started with.

The resulting code is below:

#define assert(expression) \
  if (!(expression)) \
  { \
    Serial.println(F(__FILE__)); \
    Serial.println(__LINE__, DEC); \
    Serial.flush(); \
    abort(); \
  }
1
  • 1
    About class - in this case it was used as old form of namespaces (as namespaces weren't present in c++ until 1990). However struct was used more likely as it doesn't need public: specifier.
    – KIIV
    Commented Jun 2, 2019 at 20:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.