質問

When I create an array of connections to psql database using pqxx, connections create successfully and they are in the array. But when I'm going to use one connection it gives me the following error. The way i created the array is also mentioned below. Can anyone tell me the reason for this.

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

terminate called after throwing an instance of 'pqxx::broken_connection' what(): Connection to database failed Aborted

役に立ちましたか?

解決 2

You are storing address of local variable c in conList, after first for loop, those local variables are released, conList stores dangling pointers only, invoke function call to dangling pointers has undefined behavior.

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

Consider below change?

store value instead of pointer in 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(); 

他のヒント

Your connection c is created on the stack. When the scope closes (basically, when the enclosing } is reached), the compiler runs the destructor for c. The connection will be closed, and the address that you've taken and stored in your conList now unfortunately points to junk.

The easy way around this is to create a connection on the heap using operator new, i.e.

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

at some point, when you're finished with the connections, you'll need a matching delete function:

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

This is fine, but C-style raw pointers are best avoided for a few reasons if you can help it. A better solution would be to store the connection pointer in a C++ smart pointer. This will automatically delete the connection at the right time.

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... */));
}

Now, when the conList is destroyed, all your connections will automatically be closed.

(If you're using C++11, std::unique_ptr would probably be a better choice than a shared pointer.)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top