Question

Here comes a stupid question. libpq's PQerrorMessage function return a char const*

char const* msg = PQerrorMessage(conn);

Now since it's const, I don't think I should be deallocating it and I've never seen that done in any examples. But then, when and how does it get freed? How could it know when I'm finished using my msg pointer?

At first I thought it gets deallocated once another error message is requested but that's not the case.

// cause some error
char const* msg1 = PQerrorMessage(pgconn);

// cause another error
char const* msg2 = PQerrorMessage(pgconn);

// still works
std::cout << msg1 << msg2 << std::endl;

Can someone shed some light on this for me?

Edit: credits to Dmitriy Igrishin

I asked this on the postgresql mailing list and turns out that my initial assumption was correct.
The msg1 pointer should not have been valid and I got lucky somehow.

Edit: from the postgresql docs

PQerrorMessage

Returns the error message most recently generated by an operation on the connection.

char *PQerrorMessage(const PGconn *conn);

Nearly all libpq functions will set a message for PQerrorMessage if they fail. Note that by libpq convention, a nonempty PQerrorMessage result can consist of multiple lines, and will include a trailing newline. The caller should not free the result directly. It will be freed when the associated PGconn handle is passed to PQfinish. The result string should not be expected to remain the same across operations on the PGconn structure.

Was it helpful?

Solution 2

A library function that returns a plain-old-pointer to allocated memory is very old-school and C-ish, but there are still a lot of them around. There's no way other than documentation to know if the intent of the library designer was to transfer ownership of the allocated storage to your code. The modern library designer can return a shared_ptr<> to make their intention about storage lifetime completely clear, or wrap the string up as an std::string, which also handles allocation and deletion under the covers.

The const char* declaration doesn't really say anything about the storage lifetime. Instead, it says don't modify the storage. For an old-school function that returns allocated storage, you just have to know that deleting the storage isn't the same as modifying it. The old-school function might want to return a const char* to let you know that only so many storage positions are allocated, and if you write off the end, chaos will ensue.

Of course this function might be returning data from a static table, in which case you should neither write into it nor delete it. Again, when you use plain-old-pointers, there's no way to know.

OTHER TIPS

Do as the docs say, dont expect it's contents to remain constant, just save them away in a std::string rather than storing the pointer.

// cause some error
std::string msg1 = PQerrorMessage(pgconn);

// cause another error
std::string msg2 = PQerrorMessage(pgconn);

// works all the time
std::cout << msg1 << msg2 << std::endl;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top