Я вызываю этот код из Boost Test Framework, который проверяет наличие повреждений в стеке.
Я получаю это сообщение об ошибке:
Ошибка проверки времени выполнения № 2 — стек вокруг переменной «temp» поврежден. Не имеет значения, успешно ли я открыл соединение с базой данных mysql. Если я закомментирую вызов mysql_close, я не получу такого сообщения.
Я установил MySQL Server 5.6 и я ссылаюсь на эти каталоги:
C:\Program Files\MySQL\MySQL Connector.C 6.1\lib
C:\Program Files\MySQL\Connector.C++ 1.1\lib\opt
И я бегу с DLL, которую я нашел здесь:
C:\Program Files\MySQL\MySQL Connector.C 6.1\lib\libmysql.dll
Мне интересно, если соглашение о вызовах является неправильным, так как это проект C ++? Каков был бы правильный способ исправить это? Все остальное, кажется, работает правильно, и я не получаю повреждения стека ни от одного из других вызовов mysql_.
У меня есть функция, определенная как:
void create_db(const std::string &host, const std::string &username, const std::string &password, const std::string &name)
{
MYSQL temp;
mysql_init(&temp);
if (!mysql_real_connect(&temp, host.c_str(), username.c_str(), password.c_str(), NULL, 0, NULL, 0))
{
throw mysql_db::error(mysql_error(&temp), DETAILS, mysql_errno(&temp));
}
std::string query_str("CREATE DATABASE IF NOT EXISTS "+name);
if (0 != mysql_real_query(&temp, query_str.c_str(), (unsigned long)query_str.length())) {
mysql_close(&temp);
throw database::error(mysql_error(&temp), DETAILS, mysql_errno(&temp));
}
mysql_close(&temp);
}
Я могу закомментировать все, чтобы воспроизвести эту проблему, оставив только:
void create_db(const std::string &host, const std::string &username, const std::string &password, const std::string &name)
{
MYSQL temp;
mysql_init(&temp);
mysql_close(&temp);
}
Документация MySQL для mysql_close гласит:
20.6.7.5 mysql_close ()
void mysql_close (MYSQL * mysql)
Описание
Закрывает ранее открытое соединение. mysql_close () также освобождает дескриптор соединения, на который указывает mysql, если дескриптор был автоматически выделен mysql_init () или mysql_connect ().
Поэтому я думаю, что это нормально для меня, чтобы вызвать mysql_close здесь.
Библиотека MySQL ожидает MYSQL
указатель на объект, выделенный в куче malloc()
; mysql_close()
функция в конечном итоге пытается free()
этот указатель в конце. Это не работает правильно для объекта в стеке.
Вы должны либо выделить этот объект самостоятельно, используя malloc()
или разрешить mysql_init()
выделить его самому, например,
MYSQL *temp = mysql_init(NULL);
...
mysql_free(temp);
или же
MYSQL *temp = malloc(sizeof(MYSQL));
mysql_init(temp);
...
mysql_free(temp);