以下是测试代码,程序运行一段时间以后就出现段错误,如果把OCILogon那一行代码注释起来就没事了。
这该如何解决呢?难道oracle就不支持在多线程里同时连接数据库。
#include <string.h>
#include <wchar.h>
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <semaphore.h>#include <iostream>
#include <string>
#include <map>using namespace std;#include <oci.h>
#pragma comment(lib,"libclntsh.so")bool g_flag = true;void * thread_func( void * lpParam )
{ sword status = -1; OCIEnv * envhp = NULL; // 环境句柄
OCIServer * svrhp = NULL; // 服务器句柄
OCIError * errhp = NULL; // 错误句柄
OCISvcCtx * svchp = NULL; // 服务上下文句柄 while( g_flag )
{
//printf( " prepare sleep = %u\n",&pid );
sleep( 1 ); // 创建OCI环境句柄
status = OCIEnvCreate(&envhp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCIEnvCreate failed... ID = \n" );
}
// 分配服务器句柄
status = OCIHandleAlloc ((dvoid *)envhp, (dvoid **)&svrhp,OCI_HTYPE_SERVER, 0, (dvoid **) 0);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCI_HTYPE_SERVER failed... ID = \n" );
}
// 分配错误句柄
status = OCIHandleAlloc ((dvoid *)envhp, (dvoid **)&errhp,OCI_HTYPE_ERROR, 0, (dvoid **) 0);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCI_HTYPE_ERROR failed... ID = \n" );
}
// 分配服务上下文句柄
status = OCIHandleAlloc ((dvoid *)envhp, (dvoid **)&svchp,OCI_HTYPE_SVCCTX, 0, (dvoid **) 0);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCI_HTYPE_SVCCTX failed... ID = \n" );
} char * username = "gagb";
char * password = "gagb";
char * conn = "(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.201)(PORT = 1521)) )(CONNECT_DATA = (SID = GAGB)))";
status = OCILogon( envhp,errhp,&svchp,(text *)username,(ub4)strlen(username),(text *)password,(ub4)strlen(password),(text *)conn,(ub4)strlen(conn) );
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCILogon failed... ID = %u\n",envhp );
}
else
{
sleep( 1 );
OCILogoff( svchp,errhp );
printf( "## OCILogon successed... ID = %u\n",envhp );
}
// 按照顺序依次释放相关句柄
// 释放服务上下文句柄
if( svchp != NULL )
{
OCIHandleFree(svchp, OCI_HTYPE_SVCCTX);
svchp = NULL;
}
// 释放错误句柄
if( errhp != NULL )
{
OCIHandleFree(errhp, OCI_HTYPE_ERROR);
errhp = NULL;
}
// 释放服务器句柄
if( svrhp != NULL )
{
OCIHandleFree(svrhp, OCI_HTYPE_SERVER);
svrhp = NULL;
}
// 释放OCI环境句柄
if( envhp != NULL )
{
OCIHandleFree(envhp, OCI_HTYPE_ENV);
envhp = NULL;
}
}
}void sigint_func( int signum );int main( int argc,char * argv[] )
{
signal( SIGINT,sigint_func );
int i;
pthread_t pid[50];
for( i = 0; i < 50; i++ )
{
pthread_create( &pid[i],NULL,thread_func,(void*)0 );
} for( i = 0; i < 50; i++ )
{
pthread_join( pid[i],NULL );
} return 0;
}void sigint_func( int signum )
{
g_flag = false;
}
这该如何解决呢?难道oracle就不支持在多线程里同时连接数据库。
#include <string.h>
#include <wchar.h>
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <semaphore.h>#include <iostream>
#include <string>
#include <map>using namespace std;#include <oci.h>
#pragma comment(lib,"libclntsh.so")bool g_flag = true;void * thread_func( void * lpParam )
{ sword status = -1; OCIEnv * envhp = NULL; // 环境句柄
OCIServer * svrhp = NULL; // 服务器句柄
OCIError * errhp = NULL; // 错误句柄
OCISvcCtx * svchp = NULL; // 服务上下文句柄 while( g_flag )
{
//printf( " prepare sleep = %u\n",&pid );
sleep( 1 ); // 创建OCI环境句柄
status = OCIEnvCreate(&envhp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCIEnvCreate failed... ID = \n" );
}
// 分配服务器句柄
status = OCIHandleAlloc ((dvoid *)envhp, (dvoid **)&svrhp,OCI_HTYPE_SERVER, 0, (dvoid **) 0);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCI_HTYPE_SERVER failed... ID = \n" );
}
// 分配错误句柄
status = OCIHandleAlloc ((dvoid *)envhp, (dvoid **)&errhp,OCI_HTYPE_ERROR, 0, (dvoid **) 0);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCI_HTYPE_ERROR failed... ID = \n" );
}
// 分配服务上下文句柄
status = OCIHandleAlloc ((dvoid *)envhp, (dvoid **)&svchp,OCI_HTYPE_SVCCTX, 0, (dvoid **) 0);
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCI_HTYPE_SVCCTX failed... ID = \n" );
} char * username = "gagb";
char * password = "gagb";
char * conn = "(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.201)(PORT = 1521)) )(CONNECT_DATA = (SID = GAGB)))";
status = OCILogon( envhp,errhp,&svchp,(text *)username,(ub4)strlen(username),(text *)password,(ub4)strlen(password),(text *)conn,(ub4)strlen(conn) );
if(status != OCI_SUCCESS && status != OCI_SUCCESS_WITH_INFO )
{
printf( "## OCILogon failed... ID = %u\n",envhp );
}
else
{
sleep( 1 );
OCILogoff( svchp,errhp );
printf( "## OCILogon successed... ID = %u\n",envhp );
}
// 按照顺序依次释放相关句柄
// 释放服务上下文句柄
if( svchp != NULL )
{
OCIHandleFree(svchp, OCI_HTYPE_SVCCTX);
svchp = NULL;
}
// 释放错误句柄
if( errhp != NULL )
{
OCIHandleFree(errhp, OCI_HTYPE_ERROR);
errhp = NULL;
}
// 释放服务器句柄
if( svrhp != NULL )
{
OCIHandleFree(svrhp, OCI_HTYPE_SERVER);
svrhp = NULL;
}
// 释放OCI环境句柄
if( envhp != NULL )
{
OCIHandleFree(envhp, OCI_HTYPE_ENV);
envhp = NULL;
}
}
}void sigint_func( int signum );int main( int argc,char * argv[] )
{
signal( SIGINT,sigint_func );
int i;
pthread_t pid[50];
for( i = 0; i < 50; i++ )
{
pthread_create( &pid[i],NULL,thread_func,(void*)0 );
} for( i = 0; i < 50; i++ )
{
pthread_join( pid[i],NULL );
} return 0;
}void sigint_func( int signum )
{
g_flag = false;
}
status = OCILogon( envhp,errhp,&svchp,(text *)username,(ub4)strlen(username),(text *)password,(ub4)strlen(password),(text *)conn,(ub4)strlen(conn) );
pthread_mutex_unlock(&g_mutex);好了,没有问题了, 运行多久(测试的是连续运行大约12小时,而且加锁后从来没有发现过有出错的现象)也不会出现“段错误”。如果不加互斥代码的话基本上10分钟就崩了。难道OCILogon就不支持多线程同时调用?不科学啊。好歹也是ORACLE,知名的数据库产品啊。
status = OCIEnvCreate(&envhp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);结帖。