我试图实现MS SQL ODBC连接在C++。
我想在C流上做一个瘦的RAII Package 器,因为它依赖于宏/返回代码/后藤退出语句来释放获取的资源。BLOG是示例代码,我在文档中找到:
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
#include <string.h>
#define RESULT_LEN 256
#define CHECK_ERROR(e, s, h, t) ({\
if (e!=SQL_SUCCESS && e != SQL_SUCCESS_WITH_INFO) {extract_error(s, h, t); goto exit;} \
})
void extract_error(char *fn, SQLHANDLE handle, SQLSMALLINT type)
{
SQLINTEGER i = 0;
SQLINTEGER NativeError;
SQLCHAR SQLState[7];
SQLCHAR MessageText[256];
SQLSMALLINT TextLength;
SQLRETURN ret;
fprintf(stderr, "\nThe driver reported the following error %s\n", fn);
do
{
ret = SQLGetDiagRec(type, handle, ++i, SQLState, &NativeError,
MessageText, sizeof(MessageText), &TextLength);
if (SQL_SUCCEEDED(ret)) {
printf("%s:%ld:%ld:%s\n",
SQLState, (long)i, (long)NativeError, MessageText);
}
} while (ret == SQL_SUCCESS);
}
int main()
{
SQLHENV henv = SQL_NULL_HENV; // Environment
SQLRETURN retcode;
// Allocate environment handle
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
CHECK_ERROR(retcode, "SQLAllocHandle(SQL_HANDLE_ENV)", henv, SQL_HANDLE_ENV);
exit:
printf("\nComplete.\n");
// Free handles
// Environment
if (henv != SQL_NULL_HENV)
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return 0;
}
字符串SQLHENV
只是void*
上的typedef
,它是从SQL_NULL_HENV
初始化的,然后扩展到0
。在SQLAllocHandle
中,它被更改为驱动程序管理器分配的结构的地址。
根据文档,exit
标签后的清除逻辑可能会失败,并且获取的指针将不会被释放。
如果我把这个逻辑放在析构函数中(遵循RAII准则),在驱动程序管理器无法释放资源的情况下,似乎会出现漏洞。
我相信,抛出析构函数是不好的做法,所以我真的不想走这条路。
有没有一个好的方法来处理这个问题,或者我应该接受内存泄漏的可能性?
任何帮助都欢迎。谢谢。
1条答案
按热度按时间mzaanser1#
可以合理地预期:
1.如果资源分配得当
1.它尚未被释放,并且
1.它只能在该资源的任何使用结束后被释放,否则它将不被使用,也不再以任何方式被引用
则释放资源的尝试预期会成功。
如果它失败了,这是一个灾难性的情况,没有干净的解决方案可以合理地预期存在。
在这种情况下,
abort()
通常会被调用,以在这种令人遗憾的情况下拔掉插头。注意,技巧是确保第三个条件被正确地强制执行。因此,例如,粗略地说:如果这个SQL句柄当前正在用于执行一个语句,或者以其他方式使用,那么类不能被销毁。这也需要以某种方式强制执行。