5
votes

Background: We are using Keil to compile our NXP LPC2458 project. There are numerous tasks that are being run on Keil’s RealView RTOS. There is stack space created, which is being allocated to each task. There is no HEAP created by default, and I want to avoid it since we can't afford the code-space overhead and the cost of "garbage collecting"

Objective: Use C++ in the embedded code without using the heap. Keil provides the #pragma (__use_no_heap) which prevents malloc() and free() calls to be linked.

Solution: I tried creating a Singleton with a private static pointer. My hopes were that the new() would not be called since I declared dlmData as static in the getDLMData(). For some reason, the linker still states that malloc() and free() are being called. I have thoughts of a private operator new () and a private operator delete() , and then declaring the dlmData as static within the overloaded function. It is not working for some reason. WHAT AM I DOING WRONG?

    //class declaration
    class DataLogMaintenanceData
    {
    public:
      static DataLogMaintenanceData* getDLMData();
      ~DataLogMaintenanceData()
      { instanceFlag = FALSE; }
    protected:
      DataLogMaintenaceData(); //constructor declared protected to avoid poly
    private:
      static Boolean instanceFlag;
      static DataLogMaintenceData *DLMData;
    }

    //set these to NULL when the code is first started
    Boolean DataLogMaintenanceData::instanceFlag = FALSE;
    DataLogMaintenanceData *DataLogMaintenaceData::DLMData = NULL;    

    //class functions
    DataLogMaintenanceData *DataLogMaintenanceData::getDLMData()
    {
        if (FALSE == instanceFlag)
        {
            static DataLogMaintenanceData dlmData;
            DLMData = &dlmData;
            instanceFlag = TRUE;
            return DLMData;
        }
        else
        {
            return DLMData;
        }
    }

    void InitDataLog ( void )
    {
        DataLogMaintenanceData *dlmData;
        dlmData = DataLogMaintenanceData::getDLMData();
        // to avoid dlmData warning
        dlmData = dlmData;
    }

    //ACTUAL TASK
    __task DataLog()
    {
      .. .. .. code to initialize stuff

      InitDataLog();

      .. .. ..more stuff
    }

For some reason, the only way I can get this to compile, is to create a heap space and then allow the malloc() and free() calls to be compiled into the project. As expected, the “static”ally defined object, dlmData, resides in the RAM space allocated to the dataLog.o module (i.e. it doesn’t live in the HEAP).

I can’t figure out, and I have checked Google, what am I missing? Is it possible in C++ to bypass malloc() and free() when compiling pure objects? I know I can replace the RTOS’s implementation of malloc() and free() to do nothing, but I want to avoid compiling in code that I won’t use.

3
Just make DLMData a file-level static DataLogMaintenanceData*. That's automatically initialized to NULL, so you don't need another redundant instanceFlag. And what's the point of the stack variable dlmData in InitDataLog? This code is messy.MSalters
There is no garbage collecting in C++. You deterministically manage your own memory.Mark B
Singletons -> reaping what you sow, imo.Puppy
@MSalters - you are correct, the code can be cleaned up. I was trying everything, and I should have cleansed the code before posting itembedded_parag
@MarkB - I was trying to avoid managing my own memoryembedded_parag

3 Answers

2
votes

Probably some of the code we aren't seeing calls a function that calls malloc behind the scenes.

From http://www.keil.com/support/man/docs/armlib/armlib_CJAIJCJI.htm you can use --verbose --list=out.txt on the link line to get details about the malloc caller.

2
votes

Included in the Keil installation is a set of PDFs... one of the documents (document ID DUI0475A) is titled "Using ARM C and C++ Libraries and Floating-Point Support". It discusses use of the heap (and preventing its use) in several places.

Specifically, check out section 2.64 "Avoiding the ARM-supplied heap and heap-using library functions", lots of good information there. The interesting text in that section:

You can reference the __use_no_heap or __use_no_heap_region symbols in your code to guarantee that no heap-using functions are linked in from the ARM library.

__use_no_heap guards against the use of malloc(), realloc(), free(), and any function that uses those functions. For example, calloc() and other stdio functions.

__use_no_heap_region has the same properties as __use_no_heap, but in addition, guards against other things that use the heap memory region. For example, if you declare main() as a function taking arguments, the heap region is used for collecting argc and argv.

Since your question is about how prevent malloc() from being called / used, that might put you on the right track.

0
votes

From the code you've posted I cannot see anything that would like to allocate the memory on the heap. Are there any implicit conversions taking place somewhere? What if you compile without this class at all?

What you could do:

1) Run under debugger (assuming you can build a runnable image, maybe on an emulator), set a breakpoint in malloc and examine the stack

2) Provide your own malloc and free to make linker happy, then repeat step 1.

You may find that you need to link against a different version of C runtime startup. In the worst case if number of calls to malloc/free is limited you can roll out your own version which will give the callers some preallocated memory - but hopefully this will not be neccessary.