John
John

Reputation: 11831

Why does Valgrind give "Invalid read of size 1" error?

Valgrind is giving me an invalid read error:

==37561== Invalid read of size 1
==37561==    at 0x7E81: strlen (vg_replace_strmem.c:427)

for the following code within a class (which I think may be related to a trailing \0, but I'm not sure).

std::queue<std::string> errorLog;  ///< FIFO used to store errors

const char *Monitor::popErrorFromErrorLog() {
    if (!errorLog.empty()) {
        std::string str = errorLog.front();
        errorLog.pop();
        return str.c_str();
    } else {
        return nullptr;
    }
}

void Monitor::reportError(std::string s) {
    std::ostringstream err;
    err << "Error reported: " << s << std::endl;
    errorLog.push(err.str());
}

Any ideas what's wrong here please?

Upvotes: 0

Views: 1642

Answers (2)

NathanOliver
NathanOliver

Reputation: 180630

std::string str = errorLog.front(); creates a local std::string. When you use return str.c_str(); you are returning a pointer to the c-string that std::string wraps. Once the return happens the string is destroyed and now you have returned a pointer to memory that has gone out of scope.

I would just return a std::string so you do not have to worry about that. If you cannot do that then you will have to allocate storage dynamically(new{}) and then you will have to remember to clean it up(delete[]) when you are done.

Upvotes: 1

MicroVirus
MicroVirus

Reputation: 5477

You are returning a c_str-pointer to a std::string that no longer exists: you pop it off the stack and copy its contents to a local variable, then you return the c_str pointer of that local variable, which gets destroyed as the function returns.

As for the solution, why not just return std::string rather than resorting to C strings?

Upvotes: 3

Related Questions