首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

ODBC的程序崩溃了解决思路

2012-03-28 
ODBC的程序崩溃了框架搭完了,发现ODBC连接时崩溃了,跟踪一下,就是崩溃在SQLDriverConnectAPI里,错误日志:

ODBC的程序崩溃了
框架搭完了,发现ODBC连接时崩溃了,跟踪一下,就是崩溃在SQLDriverConnect   API里,错误日志:
错误应用程序   test.exe,版本   0.0.0.0,错误模块   ole32.dll,版本   5.2.3790.2492,错误地址   0x0001f202。

因为ODBC   API我再次封装了的,总是担心内存泄露,所以每声明个内存,先把释放内存的语句写好再写其他代码,谁知道搞了一天的内存检查,发现没内存泄露,于是写了一个纯ODBC的代码进行测试,发现也崩溃了,真是找不到北了,源代码如下
#include   <stdio.h>
#include   <stdlib.h>
#include   <string.h>
#include   <windows.h>
#include   <sqlext.h>

void   dbTest()
{
        SQLHENV   henv   =   SQL_NULL_HENV;
        SQLHDBC   hdbc   =   SQL_NULL_HDBC;
        SQLHSTMT   stmt   =   SQL_NULL_HSTMT;
        SQLRETURN   ret   =   0;
        SQLINTEGER   lngId,   lngTime,   lngLength;
        SQLCHAR   strTitle[255]   =   {0};
        ret   =   SQLSetEnvAttr(SQL_NULL_HENV,   SQL_ATTR_CONNECTION_POOLING,   (SQLPOINTER)SQL_CP_ONE_PER_DRIVER,   0);
        if   (!SQL_SUCCEEDED(ret))   return;
        ret   =   SQLAllocHandle(SQL_HANDLE_ENV,   NULL,   &henv);
        if   (!SQL_SUCCEEDED(ret))   return;
        ret   =   SQLSetEnvAttr(henv,   SQL_ATTR_ODBC_VERSION,   (SQLPOINTER)SQL_OV_ODBC3,   0);
        if   (!SQL_SUCCEEDED(ret))   return;
        ret   =   SQLAllocHandle(SQL_HANDLE_DBC,   henv,   &hdbc);
        if   (!SQL_SUCCEEDED(ret))   return;
        ret   =   SQLSetConnectAttr(hdbc,   SQL_LOGIN_TIMEOUT,   (SQLPOINTER)15,   0);
        if   (!SQL_SUCCEEDED(ret))   return;
        ret   =   SQLDriverConnect(hdbc,   0,   "Driver={Microsoft   Access   Driver   (*.mdb)};DBQ=C:\\test.mdb ",   SQL_NTS,   NULL,   0,   NULL,   SQL_DRIVER_NOPROMPT);
        if   (!SQL_SUCCEEDED(ret))   return;
        ret   =   SQLAllocHandle(SQL_HANDLE_STMT,   hdbc,   &stmt);
        if   (!SQL_SUCCEEDED(ret))   return;
        ret   =   SQLExecDirect(stmt,   "SELECT   TOP   10   SEQID,TITLE,INTIME   FROM   ARTICLE ",   SQL_NTS);
        if   (!SQL_SUCCEEDED(ret))   return;
        while   (SQL_SUCCEEDED(SQLFetch(stmt)))
        {
                SQLGetData(stmt,   1,   SQL_C_LONG,   &lngId,   0,   &lngLength);
                SQLGetData(stmt,   1,   SQL_C_CHAR,   &strTitle,   sizeof(strTitle)   -   1,   &lngLength);
                SQLGetData(stmt,   3,   SQL_C_LONG,   &lngTime,   0,   &lngLength);
                printf( "%ld,%s,%ld\r\n ",   lngId,   strTitle,   lngTime);
        }
        SQLFreeHandle(SQL_HANDLE_STMT,   stmt);
        SQLFreeHandle(SQL_HANDLE_DBC,   hdbc);


        SQLFreeHandle(SQL_HANDLE_ENV,   henv);
}

int   main(int   argc,   char   *argv[])
{
        dbTest();
        return   0;
}

Debug模式编译成test.exe
然后在Debug目录下创建一个:test.bat
call   test.exe
test.bat

让程序无限循环,运行还没一分钟,弹出提示,地址不能读

[解决办法]
return之前要释放资源
不想写太多层If的话,用构造函数、析构函数来分配、释放资源,或者用do-while(false)+break
[解决办法]
第三个和第四个if判断改为:
if (!SQL_SUCCEEDED(ret))
{
SQLFreeHandle(SQL_HANDLE_ENV, henv);
return;
}

第五个,六,七个if判断改为:
if (!SQL_SUCCEEDED(ret))
{
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
  SQLFreeHandle(SQL_HANDLE_ENV, henv);
return;
}
第八个if改为:
  if (!SQL_SUCCEEDED(ret))
{
   SQLFreeHandle(SQL_HANDLE_STMT, stmt);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
   return;
}

[解决办法]
顶一下
[解决办法]
可能和系统服务设置有关

[解决办法]
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
SQLFreeHandle(SQL_HANDLE_ENV, henv);

这三个释放资源的地方,在某些条件下根本不能运行到这里。
所以必须在每一次return 前,都要做这些操作。

[解决办法]
貌似应该加上异常处理吧。
你试一下
[解决办法]
ODBC不会, 帮你顶了
[解决办法]
再顶一下

热点排行