0

I have the following classes:

MessageConstants.h:

class MessageConstants
{

public:
    ...
    static const int ErrorDescriptionLength = 256;
...
};

SystemMessage.h:

class EvtError
{
private:
    struct MsgData
    {
        int errorCode;            
        char errorDescription[MessageConstants::ErrorDescriptionLength]; 
    }__attribute__((packed)) msgData;

public:
    EvtError(int errorCode, string errorDescription);
    inline void setErrorDescription(string desc){memcpy(msgData.errorDescription, desc.c_str(),
                min(MessageConstants::ErrorDescriptionLength, (int)desc.length()));}

};

SystemMessage.cpp:

EvtError::EvtError(int errorCode, string errorDesc)
{
    memset(&msgData, '\0', sizeof(msgData));
    msgData.errorCode = errorCode;
    memcpy(msgData.errorDescription, errorDesc.c_str(), min(MessageConstants::ErrorDescriptionLength, (int)errorDesc.length()));
}

I got the following link error on SystemMessage.cpp statement memcpy(msgData.errorDescription, errorDesc.c_str(), min(MessageConstants::ErrorDescriptionLength, (int)errorDesc.length())); :

In function EvtError::EvtError(int, std::string): undefined reference to MessageConstants::ErrorDescriptionLength collect2: error: ld returned 1 exit status make: [link] Error 1

If I replace the MessageConstants::ErrorDescriptionLength with sizeof(msgData.errorDescription), the link error disappear.

My questions:

  1. Why it doesn't complain the MessageConstants::ErrorDescriptionLength in the SystemMessage.h file, where there are two places with it?

  2. How to avoid above link error?

4
  • This is because const static ints in class definitions is broken because they don't have real addresses, which is required for std::min. I'm too tired to explain properly. min((int)MessageConstants::ErrorDescriptionLength or min(+MessageConstants::ErrorDescriptionLength will fix it by making a temporary copy. Alternatively, take it out of the class as a regular const, perhaps in a namespace. Commented Jan 25, 2015 at 2:55
  • 1
    @NeilKirk Dude stop posting answers in comments. Either post an answer, or don't. Commented Jan 25, 2015 at 2:57
  • you might want to null-terminate your buffer once you fix the link error Commented Jan 25, 2015 at 2:57
  • @MattMcNabb will "memset(&msgData, '\0', sizeof(msgData));" null-terminate the buffer? Commented Jan 25, 2015 at 3:18

2 Answers 2

3

The signature of min is:

template <typename T>
const T& min(const T&, const T&);

It takes its inputs by reference - which requires them to have storage. Your constant:

static const int ErrorDescriptionLength = 256;

Does not currently have storage. There are two ways to approach this. First, you can just add storage in your .cpp:

const int MessageConstants::ErrorDescriptionLength;

Second, you can just cast it to an int:

min((int)MessageConstants::ErrorDescriptionLength, (int)errorDesc.length())
 // ^^^^^
Sign up to request clarification or add additional context in comments.

6 Comments

I have tried your first solution. It will cause compile error in SystemMessage.h file: array bound is not an integer constant before ‘]’ token
@5YrsLaterDBA What? All you added was the one line in the MessageConstants.cpp right?
I removed the "= 256" from the MessageConstants.h and then add const int MessageConstants::ErrroDescriptionLength = 256; in MessageConstants.cpp. The gcc compiler will complain then.
@5YrsLaterDBA Leave the "= 256" in the header. Everything else has to see that value.
tried that. It will cause "duplicate" compile error.
|
0

Static variable must have a definition outside the class:

const int MessageConstants::ErrorDescriptionLength ;

This should go in exactly one .cpp. file in your project.

Sometimes you can get away without it, but in those cases it is either because the variable was not odr-used, or the program was ill-formed (but ODR violations don't require diagnosis).

6 Comments

In theory this is the correct solution but I've found it not working in Visual Studio compilers.
@NeilKirk report a compiler bug then
I tried that, then I will get compile error in SystemMessage.h saying: array bound is not an integer constant before ‘]’ token
@MattMcNabb aren't you allowed to directly define static const integral types in class?
@vsoftco it all comes down to odr-use
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.