Здесь возникает глупый вопрос. libpq
«s PQerrorMessage
функция возвращает char const*
char const* msg = PQerrorMessage(conn);
Теперь, так как это const
Я не думаю, что мне следует это освобождать, и я никогда не видел, чтобы это было сделано ни в каких примерах. Но тогда, когда и как он освобождается?
Как он мог знать, когда я закончил использовать мой msg
указатель?
Сначала я думал, что он освобождается после запроса другого сообщения об ошибке, но это не так.
// cause some error
char const* msg1 = PQerrorMessage(pgconn);
// cause another error
char const* msg2 = PQerrorMessage(pgconn);
// still works
std::cout << msg1 << msg2 << std::endl;
Может кто-нибудь пролить свет на это для меня?
Редактировать: кредиты Дмитрию Игришину
я спросил это в списке рассылки postgresql и оказалось, что мое первоначальное предположение было верным.
msg1
указатель не должен был быть действительным, и мне как-то повезло.
Редактировать: из документов postgresql
PQerrorMessage
Возвращает сообщение об ошибке, которое было сгенерировано последней операцией соединения.
char *PQerrorMessage(const PGconn *conn);
Почти все функции libpq установят сообщение для
PQerrorMessage
если они потерпят неудачу. Обратите внимание, что по соглашению libpq непустойPQerrorMessage
результат может состоять из нескольких строк и включать в себя завершающий символ новой строки. Звонящий не должен освобождать результат напрямую. Он будет освобожден, когда связанныйPGconn
ручка передаетсяPQfinish
, Не следует ожидать, что результирующая строка останется неизменной при операциях наPGconn
состав.
Библиотечная функция, которая возвращает простой старый указатель на выделенную память, очень старая и C-ish, но их все еще много. Нет другого способа, кроме документации, узнать, что разработчик библиотеки намеревался передать право собственности на выделенное хранилище вашему коду. Современный дизайнер библиотеки может вернуть shared_ptr<> чтобы сделать их намерение относительно срока хранения полностью ясным, или оберните строку в std :: string, которая также обрабатывает размещение и удаление под крышками.
Объявление const char * ничего не говорит о сроке хранения. Вместо этого говорится, что не изменяйте хранилище. Для функции старой школы, которая возвращает выделенное хранилище, вы просто должны знать, что удаление хранилища — это не то же самое, что его изменение. Функция старой школы может захотеть вернуть const char *, чтобы вы знали, что выделено только столько позиций памяти, и если вы запишете конец, то наступит хаос.
Конечно, эта функция может возвращать данные из статической таблицы, и в этом случае вы не должны ни записывать, ни удалять ее. Опять же, когда вы используете обычные старые указатели, нет способа узнать.
Делайте, как говорят документы, не ожидайте, что его содержимое останется постоянным, просто сохраните их в std::string
вместо того, чтобы хранить указатель.
// 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;