1

pqxx を使用して psql データベースへの接続の配列を作成すると、接続が正常に作成され、それらが配列に含まれます。しかし、1 つの接続を使用しようとすると、次のエラーが表示されます。配列を作成した方法も以下に記載されています。この理由を誰か教えてください。

for(int i=0;i<10;i++)
    {

        connection c("dbname=test user=postgres password=abc123\
                     hostaddr=127.0.0.1 port=5432");
        conList[i]=&c;
    }

  for (int j=0;j<10;j++)
        {
            cout<<conList[j]->is_open()<<endl; // this returns 0
        }

conList[0]->activate(); // at this point it gives the following error

'pqxx::broken_connection' what() のインスタンスをスローした後に呼び出された終了: データベースへの接続に失敗しました 中止されました

4

2 に答える 2

2

あなたconnection cはスタック上に作成されます。スコープが閉じると (基本的には、囲み}に到達すると)、コンパイラは のデストラクタを実行しcます。接続は閉じられ、あなたが取得して保存したアドレスは、conList残念ながら迷惑メールを指しています.

operator newこれを回避する簡単な方法は、を使用してヒープに接続を作成することです。

for (int i = 0; i < 10; i++) {
   conList[i] = new connection(/* args... */);
}

ある時点で、接続が終了したら、対応する削除関数が必要になります。

for (int  i = 0; i < 10; i++) {
    delete conList[i];
}

これは問題ありませんが、C スタイルの生のポインターは、いくつかの理由から回避するのが最善です。より良い解決策は、接続ポインターを C++スマート ポインターに格納することです。これにより、適切なタイミングで接続が自動的に削除されます。

typedef std::shared_ptr<pqxx::connection> connection_ptr;
std::vector<connection_ptr> conList;

for (int i = 0; i < 10; i++) {
    conList.push_back(std::make_shared<pqxx::connection>(/* args... */));
}

これで、conList が破棄されると、すべての接続が自動的に閉じられます。

(C++11 を使用している場合は、std::unique_ptrおそらく共有ポインターよりも適切な選択です。)

于 2013-10-22T09:45:16.960 に答える
1

cにローカル変数のアドレスを保存していますconList。最初のforループの後、これらのローカル変数は解放され、ダングリング ポインターconListのみが保存されます。ダングリング ポインターへの関数呼び出しの呼び出しには未定義の動作があります。

for(int i=0;i<10;i++)
{

    connection c("dbname=test user=postgres password=abc123\
                 hostaddr=127.0.0.1 port=5432");
    conList[i]=&c;  // c is local variable
}   // c is released here

for (int j=0;j<10;j++)
{
    cout<<conList[j]->is_open()<<endl;  // undefined behavior
}

conList[0]->activate(); // undefined behavior

以下の変更を検討しますか?

ポインタの代わりに値を格納conList

for(int i=0;i<10;i++)
{

    connection c("dbname=test user=postgres password=abc123\
                 hostaddr=127.0.0.1 port=5432");
    conList[i] = c;  // make a copy of c
}   

for (int j=0;j<10;j++)
{
    cout<<conList[j].is_open()<<endl;  
}

conList[0].activate(); 
于 2013-10-22T09:30:16.597 に答える