I'm designing a embedded system and we have to oftenly report system fault in different code module. So I decided to create a source file to keep the error log and I'm building a struct for that. So that, every module reporting the error log and store in a data structure directly instead of keep return a false from function. I would like to get some recommendation for the necessary members.

I have some idea on the member and would like to get some suggestion to add / optimize the data structure :

struct ErrLog
{
    unsigned long ulDate;       //Store the date of error occurs    : [MSB YYMMDD LSB, decimal]
    unsigned long ulTime;       //Store the time of error occurs    : [MSB HHMMSS LSB, decimal]
    unsigned long ulCategory;   //Store which category of error occurs  : will define a list of number to indicate which category is in
    char* cErrMsg;              //Store the error msg               : is a string actually but I'm working on embedded system so try not to include huge header file
    unsigned long* ulErrData;   //Store the error value package     : in unsigned long array format
};

Although I have the idea but I not sure how the pointer going to work. If I assign a reference cErrMsg pointer to a local char array. Does the cErrMsg pointer value remain if the it leave the function block and the local char array is deleted.

For example:

unsigned long ConvertDecimalArrayToDecimal (unsigned char* ucArray, unsigned char ucLen)
{
    unsigned long ulDecimal = 0;
    unsigned char ucItr = 0;

    //Error Log items
    char cErrMsg[] = "Length missmatch while converting from decimal array to decimal";
    unsigned long ulErrData[1];
    ulErrData[0] = (unsigned long) ucLen;

    if(ucSize>=4)
    {
        // error occur here, let say i have extern the data structure here call "SysErrLog". And ignore the error log storage size, I will use link list or fixed size array later on.
        SysErrLog.ulDate = .... //will get date time from a function
        SysErrLog.ulTime = .... //will get date time from a function
        SysErrLog.ulCategory = ERR_TYPE_CONVERSION;     //the value is define in header file, and let say value ONE
        SysErrLog.cErrMsg = cErrMsg;        //reference the msg from local array here.
        SysErrLog.ulErrData = ulErrData;    //reference the msg from local array here.

        // *The last 2 assigns are for the pointer refrencing. I worry the value it pointing to will be wipe off after the code exit this function.


        return 0xFFFFFFFF;
    }

    //conversion
    for(ucItr=0; ucItr<ucLen; ucItr++)
    {
        if(ucItr!=0)
            ulDecimal *= 0x100;
        ulDecimal += ucArray[ucItr];
    }

    return ulDecimal;
}

I have some idea on the member and would like to get some suggestion to add / optimize the data structure :

One thing certainly pops to mind, include a pointer to the next error log. The reason for this is not for a linked-list linking, but that it is often the case that you want to catch an error which causes the broader function to fail and forward a broader error log out for that function, which then causes its caller to fail, etc... In other words, you want to nest the errors such that you can trace back the errors from top to bottom. It is really annoying when an error pops up from the depth of the code without any idea of the stack-trace behind it (from where and for what reason was that deep function called and failed).

So that, every module reporting the error log and store in a data structure directly instead of keep return a false from function.

Since you are posting this in the C++ forum, I must ask why you can't use exceptions? I know that embedded folks are not big fans of C++ exceptions and prefer lighter-weight alternatives (which lead to smaller code and deterministically short latency, but also produces slower code). In any case, the mechanism you are proposing is heavier, less flexible and slower than C++ exceptions, so you might consider using them instead of developing your own custom error reporting mechanism. But, of course, if you are restricted to C or Embedded C++, then you don't have that option.

Does the cErrMsg pointer value remain if the it leave the function block and the local char array is deleted.

No, the pointer will no longer be valid. Whatever data you plan to point to, it will have to be global in scope, such as a pre-allocated global struct object that you would use to store the extra information (and the same for the message string), which is the same situation as for your error-log struct objects too (will have to be a global static array of error-log structs). This is a price you will have to pay for this feature (which is part of the reason why using C++ exceptions would be a better alternative). This is also why resource-constraint systems like embedded devices and OS kernel code will use a simpler mechanism such as returning an error code and having a place to store the last error message (e.g., Windows' GetLastError / FormatMessage functions, or Linux's errno / strerror functions), instead of a more feature-rich and useful alternative like what you are proposing.

Comments
Great advice Mike :)

include a pointer to the next error log

Yes. Definately is a good info. I just figured out this problem happen before.

C++ exceptions

Ok. I will read through the exception. I never use this before in C++ and I will try on small project for testing.

No, the pointer will no longer be valid.

I would like to know how to solve this problem also. If I declare a global char array msg. It will permanent consume a memory even the link-list is not exists anymore. So I think similar to the one I have but not point to the local char array. I will use "malloc" to reserve a space for the ErrLog structure and assign the pointer value same as the char array. Is this ok or just use vector?

I will use "malloc" to reserve a space for the ErrLog structure and assign the pointer value same as the char array. Is this ok or just use vector?

If you're going to use dynamically allocated memory to store your error logs, then you'd be better off using an STL container like vector or list. That's for sure. I was assuming you wanted to avoid dynamically allocating memory during the formation of the error log, due to the fact that it creates stochastic and long latency between the formation of the error log and being able to catch it or respond to it. In embedded systems, this is often a requirement when hard-real-time constraints exist. If you don't have such constraints, then you definitely should consider using C++ exceptions which will be far more convenient and faster than that error-log scheme. By creating polymorphic exceptions, the whole problem of determining what you should include in your error-log struct will go away, since you can create custom exception classes for any given situation with whatever data members are needed for that specific situation.

This question has already been answered. Start a new discussion instead.