construction of static foo objects .. more

M

ma740988

Referencing source snippet below, the actual contruction of the foo
objects is done in a class. In that regard, I chose methods,
class1_construct and class2_construct for demonstration purposes. That
aside, I encountered source akin to what's shown below today and I was
almost convinced the source is wrought with trouble. On second thought
it appears legal. The static ptr_foo object and it's use in assignment
to other foo objects (ptr_1 etc ) at first troubled me but it's fine as
is. Correct? Of course the real issue surrounded the fact that the
ptr_1, ptr_2, ptr_3 and ptr_4 objects ar used in a thread. As a result
when the user exited the GUI application the vector of foo objects ( fv
vec ) was being called prior to destruction of the ptr_1, ptr_2 , ptr_3
and ptr_4 objects. That led to nasty error messages.

My initial recommendation (futher below )was to rid the 'statics', in
part because I thought there was a static initilization/destruction
fiasco going on. Come to think of it that's not the case. Correct?
Having said I think the ideal thing to do here involves the use of a
reference counted smart pointer. Correct?

# include <vector>
# include <sstream>
# include <string>

std::string
to_string(int i)
{
std::stringstream s;
s << i;
return s.str() ;
}

struct foo {
std::string str ;
};

typedef std::vector < foo* > foo_vec ;
foo_vec fv;
void class1_construct()
{
for ( int idx ( 0 ); idx < 4; ++idx )
{
foo *ptr_foo = new foo () ;
ptr_foo->str = to_string ( idx ) ;
fv.push_back ( ptr_foo ) ;
}
}
void class1_delete()
{
for ( foo_vec::size_type idx ( 0 );
idx < fv.size();
++idx )
{
std::cout << "delete " << std::endl;
delete fv [ idx ] ;
}
}

static foo *ptr_foo;
static foo *ptr_1;
static foo *ptr_2;
static foo *ptr_3;
static foo *ptr_4;

int main()
{
class1_construct() ;
for ( foo_vec::size_type idx ( 0 );
idx < fv.size();
++idx )
{
ptr_foo = fv [ idx ];
if ( ptr_foo->str == "1" )
{
ptr_1 = ptr_foo ;
}
if ( ptr_foo->str == "2" )
{
ptr_2 = ptr_foo ;
}
if ( ptr_foo->str == "3" )
{
ptr_3 = ptr_foo ;
}
if ( ptr_foo->str == "4" )
{
ptr_4 = ptr_foo ;
}
}
class1_delete() ;

}


Initial recommendation



foo *ptr_1;
foo *ptr_2;
foo *ptr_3;
foo *ptr_4;

int main()
{
class1_construct() ;
for ( foo_vec::size_type idx ( 0 );
idx < fv.size();
++idx )
{
foo *ptr_foo = fv [ idx ];
if ( ptr_foo->str == "1" )
{
ptr_1 = ptr_foo ;
}
if ( ptr_foo->str == "2" )
{
ptr_2 = ptr_foo ;
}
if ( ptr_foo->str == "3" )
{
ptr_3 = ptr_foo ;
}
if ( ptr_foo->str == "4" )
{
ptr_4 = ptr_foo ;
}
}
class1_delete() ;

}
 
A

Alan Johnson

ma740988 said:
Referencing source snippet below, the actual contruction of the foo
objects is done in a class. In that regard, I chose methods,
class1_construct and class2_construct for demonstration purposes. That
aside, I encountered source akin to what's shown below today and I was
almost convinced the source is wrought with trouble. On second thought
it appears legal. The static ptr_foo object and it's use in assignment
to other foo objects (ptr_1 etc ) at first troubled me but it's fine as
is. Correct? Of course the real issue surrounded the fact that the
ptr_1, ptr_2, ptr_3 and ptr_4 objects ar used in a thread. As a result
when the user exited the GUI application the vector of foo objects ( fv
vec ) was being called prior to destruction of the ptr_1, ptr_2 , ptr_3
and ptr_4 objects. That led to nasty error messages.

My initial recommendation (futher below )was to rid the 'statics', in
part because I thought there was a static initilization/destruction
fiasco going on. Come to think of it that's not the case. Correct?
Having said I think the ideal thing to do here involves the use of a
reference counted smart pointer. Correct?

At global scope, the "static" keyword affects linkage, not lifetime, so
a static initialization/destruction fiasco would not be affected. The
only thing that changes when you remove the "static" keyword from
ptr_1, ptr_2, ptr_3, and ptr_4 is that now they may be referenced by
another translation unit (one that declares them with something like
"extern foo *ptr_1;").

In a quick examination, I don't see anything wrong with the code you
posted, with or without the statics. Does it cause some error on your
system?
 
M

ma740988

Alan said:
At global scope, the "static" keyword affects linkage, not lifetime, so
a static initialization/destruction fiasco would not be affected. The
only thing that changes when you remove the "static" keyword from
ptr_1, ptr_2, ptr_3, and ptr_4 is that now they may be referenced by
another translation unit (one that declares them with something like
"extern foo *ptr_1;").
Perhaps I'm mistaken (time to brush up again) but I thought the ones
with the static keyword could also be referenced in another translation
unit, except now I don't need extern?
In a quick examination, I don't see anything wrong with the code you
posted, with or without the statics. Does it cause some error on your
system?
Well there's a piece that I may or may not have mentioned, which
involved the desctruction of the vector on exit. ptr_1, ptr_2, ptr_3
and ptr_4 was used in a thread and from the looks of it the vector of
objects was destroyed prior to deleting the thread. As a result I was
seeing alot of 'undefined behavior ( crash) ' errors.
 
S

Steve Pope

This is a bit of a tangent, but is it typical and/or correct
to refer to a function like class1_construct() as a constructor?
To me it's not a constructor but a global function, not part of any
class, operating on a free-floating object.

Steve
 
S

Steve Pope

ma740988 said:
Alan Johnson wrote:
Perhaps I'm mistaken (time to brush up again) but I thought the ones
with the static keyword could also be referenced in another translation
unit, except now I don't need extern?

What Alan said -- static at global scope is a holdover from C,
deprecated in C++, which makes the name invisible to other translation
units. If you have "static int foo" in one translation unit and
"extern int foo" in a second translation unit, they will never
reference the same variable. (And you will need a plain "int foo"
somewhere for the extern to resolve.)

Officially, you should now use a nameless namespace to make a name
visible in only one translation unit, instead of global "static".

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,705
Latest member
Stefkari24

Latest Threads

Top