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:
- How can I get rid of the segmentation fault?
- How can it be that about 332 bytes are used for one two additional print statements? (maybe related to the const char* buffering (?)
1 Answer 1
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(); \
}
-
1About
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 needpublic:
specifier.KIIV– KIIV2019年06月02日 20:46:53 +00:00Commented Jun 2, 2019 at 20:46
Explore related questions
See similar questions with these tags.
F(__FILE__)
andF(__func__)
. (change the parameter type to __FlashStringHelper)__FILE__
but not for__func__
. Anyway usingF( __FILE__)
was about -90B difference (It's probably full path and it was only used in one file).