Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > STL & pipe, socket descriptors

Reply
Thread Tools

STL & pipe, socket descriptors

 
 
M.Endraszka@gmail.com
Guest
Posts: n/a
 
      06-16-2007

Hi,

I am writing a simple irc-like server and came across weird behavior
while debugging. Could anyone tell me why the following happens :

I have a class which stores pipe descriptors as a member field.
Descriptors are initialized with pipe(descr) in class constructor.
Then I have an array of objects of this class, preferably a STL
vector. If I initialize the vector with:

vector<object> objects(20);

all the objects have the same pipe descriptors (pipes are the same &
there is no point in have 20 of them)
this happens if I initialize with objects.push_back(...) as well. If I
initilize objects like that :

object* first_object = new object;
object* second_object = new object;

it is ok. (the descriptors given by pipe(descr); are different)

I want to use STL vector/list/whatever but it just doesn't work. I can
understand that vector<object> objects(20); may construct just one
object and then copy it 20 times, but shouldn't push_back() be any
better?

Please help.

Marcin Endraszka

 
Reply With Quote
 
 
 
 
Robert Bauck Hamar
Guest
Posts: n/a
 
      06-16-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

>
> Hi,
>
> I am writing a simple irc-like server and came across weird behavior
> while debugging. Could anyone tell me why the following happens :
>
> I have a class which stores pipe descriptors as a member field.
> Descriptors are initialized with pipe(descr) in class constructor.
> Then I have an array of objects of this class, preferably a STL
> vector. If I initialize the vector with:
>
> vector<object> objects(20);


this calls

vector<object>::vector(vector<object>::size_type, const object& t=object());

so the definition of objects is the same as if you wrote

vector<object> objects(20, object());

and this creates 20 copies of the temporary created as second argument.

> all the objects have the same pipe descriptors (pipes are the same &
> there is no point in have 20 of them)
> this happens if I initialize with objects.push_back(...) as well.


What do you mean initialize with push_back?

vector<object> objects;
for (int i = 0; i < 20; ++i)
objects.push_back(object());

?

It's hard to guess without seeing any code.

--
rbh
 
Reply With Quote
 
 
 
 
John Harrison
Guest
Posts: n/a
 
      06-16-2007
(E-Mail Removed) wrote:
> Hi,
>
> I am writing a simple irc-like server and came across weird behavior
> while debugging. Could anyone tell me why the following happens :
>
> I have a class which stores pipe descriptors as a member field.
> Descriptors are initialized with pipe(descr) in class constructor.
> Then I have an array of objects of this class, preferably a STL
> vector. If I initialize the vector with:
>
> vector<object> objects(20);
>
> all the objects have the same pipe descriptors (pipes are the same &
> there is no point in have 20 of them)
> this happens if I initialize with objects.push_back(...) as well. If I
> initilize objects like that :
>
> object* first_object = new object;
> object* second_object = new object;
>
> it is ok. (the descriptors given by pipe(descr); are different)
>
> I want to use STL vector/list/whatever but it just doesn't work. I can
> understand that vector<object> objects(20); may construct just one
> object and then copy it 20 times, but shouldn't push_back() be any
> better?
>
> Please help.
>
> Marcin Endraszka
>


Post some code. Probably your definition of object is wrong, but who can
say without seeing some code.

john
 
Reply With Quote
 
M.Endraszka@gmail.com
Guest
Posts: n/a
 
      06-16-2007
On 16 Cze, 21:08, Robert Bauck Hamar <(E-Mail Removed)> wrote:
> It's hard to guess without seeing any code.


class object
{
public:
int p[2];

object(int id)
{
pipe(p);
printf("Object %d has descriptor %d.",id,p[0]);
}

~object()
{
close(p[0]);
close(p[1]);
}
};


Static array of those will return eg.

object objects[3];
Object 1 has descriptor 7.
Object 2 has descriptor 9.
Object 3 has descriptor 11. (there are pairs of them of
c.)

STL vector will return:

vector<object> objects;
objects.push_back(1);objects.push_back(2);objects. push_back(3);

Object 1 has descriptor 7.
Object 2 has descriptor 7.
Object 3 has descriptor 7.

Which is totally not what I want. What's more if there was a socket
descriptor no.7 before, I may get same pipe descriptor AND socket
descriptor at the same time, which is so wrong.

Ask whatever you need.

Marcin

 
Reply With Quote
 
Thomas J. Gritzan
Guest
Posts: n/a
 
      06-16-2007
(E-Mail Removed) wrote:
> Static array of those will return eg.
>
> object objects[3];
> Object 1 has descriptor 7.
> Object 2 has descriptor 9.
> Object 3 has descriptor 11. (there are pairs of them of
> c.)
>
> STL vector will return:
>
> vector<object> objects;


Try at this point:

objects.reserve(3);

> objects.push_back(1);objects.push_back(2);objects. push_back(3);
>
> Object 1 has descriptor 7.
> Object 2 has descriptor 7.
> Object 3 has descriptor 7.
>
> Which is totally not what I want.


You definitly violate the "rule of three". That may be the problem here.
Google for it. If it works with a reserve(3) in this example, that this is
your problem. The vector copies your objects and makes temporaries which
get destructed, closing your pipes. So the next pipe gets an old yet unused
descriptor.

--
Thomas
http://www.netmeister.org/news/learn2quote.html
 
Reply With Quote
 
Robert Bauck Hamar
Guest
Posts: n/a
 
      06-16-2007
(E-Mail Removed) wrote:

> On 16 Cze, 21:08, Robert Bauck Hamar <(E-Mail Removed)> wrote:
>> It's hard to guess without seeing any code.

>
> class object
> {
> public:
> int p[2];
>
> object(int id)
> {
> pipe(p);
> printf("Object %d has descriptor %d.",id,p[0]);
> }
>
> ~object()
> {


I'll give you a hint. Insert

printf("Descriptors %d and %d closed\n", p[0], p[1]);

here.

> close(p[0]);
> close(p[1]);
> }
> };



--
rbh
 
Reply With Quote
 
M.Endraszka@gmail.com
Guest
Posts: n/a
 
      06-16-2007
On 16 Cze, 22:38, "Thomas J. Gritzan" <(E-Mail Removed)> wrote:
> You definitly violate the "rule of three". That may be the problem here.
> Google for it. If it works with a reserve(3) in this example, that this is
> your problem. The vector copies your objects and makes temporaries which
> get destructed, closing your pipes. So the next pipe gets an old yet unused
> descriptor.


Ok. I see the sequence is CONSTRUCT TEMP -> COPY TO DESTINATION ->
DESTROY TEMP
which I don't like, but still makes sense

Writing a copy constructor seems to help

object(object const& in)
{
id = in.id;
pipe(p);
}

I also added assigment operator as one of you suggested:

object& operator=(const object& in)
{
p[0] = in.p[0];
p[1] = in.p[1];
}

Though I think compiler generated one would do the same.
Thanks for mentioning the "rule of three"

Cheers

 
Reply With Quote
 
Robert Bauck Hamar
Guest
Posts: n/a
 
      06-16-2007
(E-Mail Removed) wrote:

> On 16 Cze, 22:38, "Thomas J. Gritzan" <(E-Mail Removed)> wrote:
>> You definitly violate the "rule of three". That may be the problem here.
>> Google for it. If it works with a reserve(3) in this example, that this
>> is your problem. The vector copies your objects and makes temporaries
>> which get destructed, closing your pipes. So the next pipe gets an old
>> yet unused descriptor.

>
> Ok. I see the sequence is CONSTRUCT TEMP -> COPY TO DESTINATION ->
> DESTROY TEMP
> which I don't like, but still makes sense.


It's what C++ does.

> Writing a copy constructor seems to help
>
> object(object const& in)
> {
> id = in.id;
> pipe(p);
> }


IMHO, this is the wrong solution. It creates a lot of pipes, and it makes
the object harder to use (copies aren't equal as one would usually expect).

> I also added assigment operator as one of you suggested:
>
> object& operator=(const object& in)
> {
> p[0] = in.p[0];
> p[1] = in.p[1];
> }
>
> Though I think compiler generated one would do the same.


Your compiler would generate the same thing. You need the rule of three, but
not this way.

Solution 1)
class object {
... //as before
private:
void operator = (const object&); // No need to actually implement these
object(const object&);
};

vector<boost::shared_ptr<object> > objects;
for (...)
objects.push_back(boost::shared_ptr<object>(new object(i)));

This would make the objects non copyable, and your boost::shared_ptr takes
care of deleting. You could also use std::auto_ptr instead of
boost::shared_ptr.

Solution 2)
class object {
struct arr {
int p[2];
};
boost::shared_ptr<arr> p;
public:
object() : p(new arr)
{ pipe(p->p); }
// compiler generated copy ctor, assignment op and dtor works
//...
};

Boost::shared_ptr can be downloaded from <URL:http://boost.org>. It's also
up for the new standard, and might be found if your compiler ships the tr1
libs. In that case it's called std::tr1::shared_ptr (turn on tr1 and
#include <memory>)

--
rbh
 
Reply With Quote
 
Diego Martins
Guest
Posts: n/a
 
      06-18-2007
On Jun 16, 7:34 pm, Robert Bauck Hamar <(E-Mail Removed)>
wrote:
> vector<boost::shared_ptr<object> > objects;
> for (...)
> objects.push_back(boost::shared_ptr<object>(new object(i)));
>
> This would make the objects non copyable, and your boost::shared_ptr takes
> care of deleting. You could also use std::auto_ptr instead of
> boost::shared_ptr.


no, you couldn't

Diego

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: socket.unbind or socket.unlisten? - socket.error: (48, 'Addressalready in use') Steve Holden Python 0 02-01-2009 12:45 PM
Re: socket.unbind or socket.unlisten? - socket.error: (48, 'Addressalready in use') Laszlo Nagy Python 0 02-01-2009 07:37 AM
socket.unbind or socket.unlisten? - socket.error: (48, 'Addressalready in use') Laszlo Nagy Python 1 01-27-2009 05:05 PM
Re: socket.unbind or socket.unlisten? - socket.error: (48,'Address already in use') Jean-Paul Calderone Python 0 01-27-2009 01:41 PM
Closing socket file descriptors Yang Python 3 05-20-2007 10:26 AM



Advertisments