[pgsql-jp: 35651] Re: libPQのPQexec関数がメモリリークで落ちます

大西 義人 yoshito @ noveluck.co.jp
2005年 7月 4日 (月) 11:31:06 JST


こんにちわ。大西です。
石井様、水野様にご指摘いただいた箇所を検証してみました。

>>ところで「メモリリークが発生して」とありますが,そう判断した根拠は何な
>>んでしょうか?それを示せばもっとよいアドバイスを得られるかも.

>>プログラムが即時に落ちるようなエラーなら、メモリリークよりも
>>セグメント境界エラーとかNULL参照ではないかと思うのですが
>>違いますか?

メモリリークではないですね。
用語を間違っていました。すみません。
正確にはこのようなメッセージです。

---------------------------
デバッガ例外が発生
---------------------------
プロジェクト Samplebpr.exe が EAccessViolation クラスの例外を生成しました。
'アドレス 326663F0 でアドレス F87206C0 に対する読み込み違反がおきました。'
プロセスは停止しています。再開するにはステップ実行または実行を選択してください。


>>手元にソースを読める環境がないのできっちり追った訳では
>>ないですが、PQexec関数自身はSQL文の構文解析なんて
>>せずPostgreSQL本体に渡してるだけだと思います。

PQexec関数の中身はおっしゃる通りです。
PQexec関数の内部で引き渡す直前の文字列をファイルに書き出したのですが、
特に問題ありませんでした。(コピーしてPGAdmin実行すればSQLは走ります)


>>自作Cアプリケーションがバグっている,に1票.

>>私としては自作PGのバグ説、もしくはlibpqのコンパイルを
>>失敗してる説に1票です

使用しているソースは下記のものです。(ほとんどサンプルそのまんまですが)
ほぼ同じソースでVCでは問題なく動いたので、
C++Builder用のDLL作成をするときの、
コンパイル方法がまずいのでしょうか・・・
一応コンパイルし直してみたのですが、結果は同じでした。


//---------------------------------------------------------------------------

#include <vcl.h>
#include <stdio.h>
#include "libpq-fe.h"

#pragma hdrstop

/*************************************************************************************
' 関数宣言
'*************************************************************************************/
PGconn* DBconnect(char *conninfo);
PGresult*  DBexec(PGconn *conn, char *command);

//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{
    char		Conninfo[256+1];
    char		ID[256+1];
    char		PWD[256+1];
    PGconn		*Conn;
    PGresult	*Res;


    // 初期化
    memset(Conninfo,0,sizeof(Conninfo));
    memset(ID ,0,sizeof(ID));
    memset(PWD,0,sizeof(PWD));
    strcpy(ID,"postgres");
    strcpy(PWD,"postgres");


    // DBの接続
    sprintf(Conninfo, "host=localhost dbname=template1 user=%s password=%s",ID,PWD);
    Conn = DBconnect(Conninfo);

    if (Conn == NULL){
        return -1;
    }

    Res = DBexec(Conn, "DROP DATABASE fscmsdb");
    if ( Res != NULL ){
         PQclear(Res);
    }else{
        return -1;
    }

    Res = DBexec(Conn, "CREATE DATABASE fscmsdb TEMPLATE template0
    ENCODING 'UTF-8'" );
   if ( Res != NULL ){
        PQclear(Res);
   }else{
        return -1;
   }

   PQfinish(Conn);

   // DBの接続
   sprintf(Conninfo, "host=localhost dbname=fscmsdb user=%s
   password=%s",ID,PWD);
   Conn = DBconnect(Conninfo);
   if(Conn == NULL){
       return -1;
    }

    static char www[] = "create table hoge (id int, value int, txt TEXT,PRIMARY KEY(id));";

    //  ここでのPQexecで落ちる 
    Res = DBexec(Conn, www);
    if(Res != NULL ){
       PQclear(Res);
    }
    PQfinish(Conn);
    return 0;
}
//---------------------------------------------------------------------------


/*************************************************************************************
' 関数名        :DBconnect
' 処理概要      :データベース接続
'*************************************************************************************/
PGconn* DBconnect(char *conninfo)
{
    PGconn		*conn;
    
	conn = PQconnectdb(conninfo);

	if ( PQstatus(conn) != CONNECTION_OK ){

		//sprintf(stderr, "DB connect failed: %s\n", PQerrorMessage(conn));
		PQfinish(conn);
		return NULL;
	}
    
	return conn;
}


/*************************************************************************************
' 関数名        :DBexec
' 処理概要      :データベースコマンド実行
'*************************************************************************************/
PGresult*  DBexec(PGconn *conn, char *command)
{
	PGresult	*res;

	res = PQexec(conn, command);

	if (PQresultStatus(res) != PGRES_COMMAND_OK){
		fprintf(stderr, "'%s' command failed: %s", command, PQerrorMessage(conn));
		PQclear(res);
		return NULL;
	}

	return res;
}





pgsql-jp メーリングリストの案内