By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,143 Members | 1,919 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,143 IT Pros & Developers. It's quick & easy.

static data-member undefined external

P: n/a
The following program compiles fine but elicits this message from the
linker: "undefined reference to VarArray::funct" and thus fails.

It seems to behave as if the static data-member: VarArray::funct were
an extern, but it is declared in the same file (q.v.). What is the
remedy for this?

=================

#include <iostream.h>

typedef void (*Funct)(int,int); // TYPE OF THE STATIC DATA-MEMBER
class VarArray
{
static Funct funct; // HERE IS WHERE THE STATIC MEMBER IS DECLARED
double* rows; // -> vector of doubles
int order; // length of vector
public:

VarArray(int n) { order = n; rows = new double[order]; }
~VarArray() {}

friend void SetVarArrayHandler(Funct); // WILL INIT STATIC MEMBER

double& operator[](int index)
{
if (index > -1 && index < order) return rows[index];
else (*funct)(index, order); // index < 0 or index > order-1
}
};
void SetVarArrayHandler(Funct fp)
{ VarArray::funct = fp; } // INITS STATIC MEMBER TO: fp (= Quit)
void Quit(int ndx, int len)
{
cerr << "index = " << ndx << " is out of bounds: [0 ... "
<< len-1 << "] -- quitting\n";
exit(-1); // ABEND
}

int main()
{
SetVarArrayHandler(Quit); // WILL INIT STATIC MEMBER TO: Quit
VarArray mat(3); // similar to: VarArray mat[3]

cout << "mat[5] = " << mat[5] << endl; /* should invoke: Quit() */
return 0;
}

Jul 22 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a

"Scott J. McCaughrin" <sj******@bluestem.prairienet.org> wrote in message
news:cm**********@wildfire-pl.prairienet.org...
The following program compiles fine but elicits this message from the
linker: "undefined reference to VarArray::funct" and thus fails.

It seems to behave as if the static data-member: VarArray::funct were
an extern, but it is declared in the same file (q.v.). What is the
remedy for this?


Define VarArray::funct, didn't I explain this before?

Add this code (not to a header file)

Funct VarArray::funct; // HERE IS WHERE THE STATIC MEMBER IS DEFINED!!!!

It's just like a global varaible, you can declare it in as many header files
as you like but you must defined it somewhere (and once only).

john
Jul 22 '05 #2

P: n/a
John Harrison <jo*************@hotmail.com> wrote:

: Add this code (not to a header file)

: Funct VarArray::funct; // HERE IS WHERE THE STATIC MEMBER IS DEFINED!!!!

: It's just like a global varaible, you can declare it in as many header files
: as you like but you must defined it somewhere (and once only).

: john

John,

Thank you for this info -- I will try it out.

However, this is a _private_ data-member -- it is not only static but
private as well.

Are you sure this is appropriate, making a private member "just like a
global"? It may be that access is still restricted, but what about the
so-called "information hiding" that 'private' is supposed to ensure?
-- Scott
Jul 22 '05 #3

P: n/a
Scott J. McCaughrin wrote:
John Harrison <jo*************@hotmail.com> wrote:

: Add this code (not to a header file)

: Funct VarArray::funct; // HERE IS WHERE THE STATIC MEMBER IS DEFINED!!!!

: It's just like a global varaible, you can declare it in as many header files
: as you like but you must defined it somewhere (and once only).

: john

John,

Thank you for this info -- I will try it out.

However, this is a _private_ data-member -- it is not only static but
private as well.

Are you sure this is appropriate, making a private member "just like a
global"?
It's not just "appropriate", it's required. Every static data member
shall be defined at the namespace level if it's used in the program
_outside_ the class definition or if it's of non-integral type (or both).
It may be that access is still restricted, but what about the
so-called "information hiding" that 'private' is supposed to ensure?


Don't you give your header to the people who're going to use your class?
What about "information hiding" in that case? Think about it.

V
Jul 22 '05 #4

P: n/a
John Harrison <jo*************@hotmail.com> wrote:

: "Scott J. McCaughrin" <sj******@bluestem.prairienet.org> wrote in message
: news:cm**********@wildfire-pl.prairienet.org...
: > The following program compiles fine but elicits this message from the
: > linker: "undefined reference to VarArray::funct" and thus fails.
: >
: > It seems to behave as if the static data-member: VarArray::funct were
: > an extern, but it is declared in the same file (q.v.). What is the
: > remedy for this?
: >

: Define VarArray::funct, didn't I explain this before?
No.

: Add this code (not to a header file)

Why should I?

: Funct VarArray::funct; // HERE IS WHERE THE STATIC MEMBER IS DEFINED!!!!

No, it was declared as a statuc member within the class, making this
extra declaration redundant.

: It's just like a global varaible, you can declare it in as many header files
: as you like but you must defined it somewhere (and once only).

: john

That is precisely the problem. To quote B.S. in Section 10.2.4 (Static
Members) of "C++ Programming Language" (3rd Edition):

"Maybe 'just one little global variable' isn't too unmanagemable, but
that style leads to code that is useless except to its original
programmer. It should be avoided."

And I agree with B.S. Here is an example of why.

Suppose someone just happens to declare an array as a global just before
your "just liek a global" declaration, say:

Funct test_array[5];
: Funct VarArray::funct; // HERE IS WHERE THE STATIC MEMBER IS DEFINED!!!!
Then they make this assignment: test_array[5] = (Funct)NULL;

Need I say more? Is this not a classic example of why globals should be
avoided?

Now, this begs the question: how am I to declare/define a static member
variable, if I cannot do it within the class? Follow the example of the
vtbl, used to implement virtual functions. The vtbl for a class is a
de facto static member, yet is not explicitly declared by the user. It
is _not_ a global, so the side-effect problems plaguing globals don't
affect it. Yet it still remains accessible to those object requiring it,
via the vptr.

My point here is simply that the static member was introduced in Section
10.2.4 as an antidote for global variables, yet the necessity of declaring
it "like a global" defeats that purpose.
Jul 22 '05 #5

P: n/a
Victor Bazarov <v.********@comacast.net> wrote:
: Scott J. McCaughrin wrote:
: > John Harrison <jo*************@hotmail.com> wrote:
: >
: > : Add this code (not to a header file)
: >
: > : Funct VarArray::funct; // HERE IS WHERE THE STATIC MEMBER IS DEFINED!!!!
: >
: > : It's just like a global varaible, you can declare it in as many header files
: > : as you like but you must defined it somewhere (and once only).
: >
: > : john
: >
: > John,
: >
: > Thank you for this info -- I will try it out.
: >
: > However, this is a _private_ data-member -- it is not only static but
: > private as well.
: >
: > Are you sure this is appropriate, making a private member "just like a
: > global"?

: It's not just "appropriate", it's required. Every static data member
: shall be defined at the namespace level if it's used in the program
: _outside_ the class definition or if it's of non-integral type (or both).

No, it should _not_ be required: it is only necessary at present because
the implementation (_not_ the language specification) requires it. That
is, the implementations I have seen do not have the compiler defining the
static member, so the user is expected to define it explicitly. Show me
how the language's specification requires this -- it does not. A compiler
could treat explicit static members the same way it does implicit statics,
like the vtbl. The user is unable to define this, so the compiler defines
it, then implements the vptr to access it. Thus, the "requirement" to
explicitly define declared static members ensues from the implementations.

: > It may be that access is still restricted, but what about the
: > so-called "information hiding" that 'private' is supposed to ensure?

: Don't you give your header to the people who're going to use your class?
: What about "information hiding" in that case? Think about it.

What does that have to do with it? Suppose the recipient of my headers is
only concerned about the interface with publicly-declared functions, and
may not even know enough about the language to be concerned about your
requirement to explicitly define its static members?

But "information hiding" here refers to security against unintended access
to private members (static or otherwise). If I have to declare a static
member at global level, here is what can happen:

Funct array[5];
Funct VarArray::funct; // a private static member of VarArray

then: array[5] = (Funct)NULL; // unintended access to private member

Think about that.

Jul 22 '05 #6

P: n/a
"Scott J. McCaughrin" <sj******@bluestem.prairienet.org> wrote...
Victor Bazarov <v.********@comacast.net> wrote:
: Scott J. McCaughrin wrote:
: > John Harrison <jo*************@hotmail.com> wrote:
: >
: > : Add this code (not to a header file)
: >
: > : Funct VarArray::funct; // HERE IS WHERE THE STATIC MEMBER IS
DEFINED!!!!
: >
: > : It's just like a global varaible, you can declare it in as many
header files
: > : as you like but you must defined it somewhere (and once only).
: >
: > : john
: >
: > John,
: >
: > Thank you for this info -- I will try it out.
: >
: > However, this is a _private_ data-member -- it is not only static but
: > private as well.
: >
: > Are you sure this is appropriate, making a private member "just like a
: > global"?

: It's not just "appropriate", it's required. Every static data member
: shall be defined at the namespace level if it's used in the program
: _outside_ the class definition or if it's of non-integral type (or
both).

No, it should _not_ be required: it is only necessary at present because
the implementation (_not_ the language specification) requires it. That
is, the implementations I have seen do not have the compiler defining the
static member, so the user is expected to define it explicitly. Show me
how the language's specification requires this -- it does not.
The only source of information I have about the language specification is
the C++ language International Standard. In 9.4.2, paragraph 2, it says,
"The definition for a static data member shall appear in a namespace scope
enclosing the member's class definition." To me "shall" means "required".
A compiler
could treat explicit static members the same way it does implicit statics,
like the vtbl.
What's "vtbl"? I can't find that word in the language Standard.
The user is unable to define this, so the compiler defines
it, then implements the vptr to access it.
There is no reference to any of it in the language specification.
Thus, the "requirement" to
explicitly define declared static members ensues from the implementations.
I somehow naively thought that it's the implementations that ensue from
the requirements set forth by the language Standard document... I guess
I was wrong then...

: > It may be that access is still restricted, but what about the
: > so-called "information hiding" that 'private' is supposed to ensure?

: Don't you give your header to the people who're going to use your class?
: What about "information hiding" in that case? Think about it.

What does that have to do with it? Suppose the recipient of my headers is
only concerned about the interface with publicly-declared functions, and
may not even know enough about the language to be concerned about your
requirement to explicitly define its static members?
I don't understand how what the recipient's "concerned about" relates to
the fact that the compiler needs all the information necessary to properly
create code that uses the objects of your class.
But "information hiding" here refers to security against unintended access
to private members (static or otherwise). If I have to declare a static
member at global level, here is what can happen:

Funct array[5];
Funct VarArray::funct; // a private static member of VarArray

then: array[5] = (Funct)NULL; // unintended access to private member
What? Huh? What unintended access? This code has _undefined_ behaviour.
There can be no "intent" here.
Think about that.


Nothing to think about. Undefined behaviour is undefined behaviour.
If you want to convince anybody that there can be something _definite_
about the code you presented here, sorry, you're mistaken.

V
Jul 22 '05 #7

P: n/a
Victor Bazarov <v.********@comacast.net> wrote:

"Scott J. McCaughrin" <sj******@bluestem.prairienet.org> wrote...
: > Victor Bazarov <v.********@comacast.net> wrote:
: > : Scott J. McCaughrin wrote:
: > : >

(intermediate commentary elided for brevity)

: > : > Are you sure this is appropriate, making a private member
: > : > "just like a global"?

: It's not just "appropriate", it's required. Every static data member
: shall be defined at the namespace level if it's used in the program
: _outside_ the class definition or if it's of non-integral type (or
: both).
(more intermediate responses frome me deleted for brevity)

: The only source of information I have about the language specification is
: the C++ language International Standard. In 9.4.2, paragraph 2, it says,
: "The definition for a static data member shall appear in a namespace scope
: enclosing the member's class definition." To me "shall" means "required".

Victor:

Thank you for citing the exact reference in the Standard, as it does shed
light on my concern. Our exchange went:

: > : > Are you sure this is appropriate, making a private member
: > : > "just like a global"?
: It's not just "appropriate", it's required.


Yet, note omssion of the term "global" from your citation, which tells me
that the Standard does not require static data members to reside in auto
storage, thus permitting them to reside in static storage as I maintained.

I suspect some of the confusion in this thread may arise from differing
interpretations of that term: "required". You take it to mean whatever
is stipulated by the Standard, while I read it to convey whatever a
compiler was capable of implementing.

: > But "information hiding" here refers to security against unintended
: > access to private members (static or otherwise). If I have to declare
: > a static member at global level, here is what can happen:
: >
: > Funct array[5];
: > Funct VarArray::funct; // a private static member of VarArray
: >
: > then: array[5] = (Funct)NULL; // unintended access to private member

: What? Huh? What unintended access? This code has _undefined_ behaviour.
: There can be no "intent" here.

Correct, which is why I said "unintended access". The behavior is indeed
"undefined" since alignment and padding considerations (if any) make it
so. But it is the _possibility_ of such access that worries me. Since
`array[]' and `funct' are of the same type, it is indeed possible that
the five elements array[0] ... array[4] can immediately precede `funct'
in auto store, so that array[5] coincides with `funct' and thereby
allow the spurious overwrite. Now, I readily concede that consigning
the private static member `funct' to static store does not guarantee
safety, but it can lessen the likelihood in cases where the static
store is treated less casually than the stack is. That may be the
best we can ever hope for.

: > Think about that.

: Nothing to think about. Undefined behaviour is undefined behaviour.
: If you want to convince anybody that there can be something _definite_
: about the code you presented here, sorry, you're mistaken.

But I am not trying to do that: only to show the possibility. Where did
I claim this would "definitely" happen, Victor? Indeed, if there is any
misperception of definiteness at all, it may accrue from use of the term
"private" to suggest that such data members are safe from unwarranted
intrusion, when my example was only submitted to assail that contention.

To put these matters into perspective, you may recall that my original
post dealt with the compiler (GNU gpp) complaining about my static data
member as an "undefined reference" (although I suspect it was the linker
complaining). Well, that means that the symbol for my static data member
could not be resolved to any kind of address, i.e., no storage had been
set aside for it, despite my declaration of it in the class as a static.
Thus, it was treating the symbol like an `extern' (I suspect other
loaders might have even given me "undefined extern" as a more inform-
ative diagnostic).

I do not agree that the user should have to define storage for a class-
level static member separate from its declaration, and so I submitted
my suggestion that -- like any non-class static variable -- it be
allocated in the static store implicity by the compiler when it first
encounters the symbol. Thus the symbol does have a memory address to
satisfy the linker.

I only raised the "vtbl" issue by way of showing how the compiler can
automatically define the static data member in static store without the
necessity of an explicit definition from the user separate from his/her
delcaration in its class. I am quite sure others can suggest far better
examples to illustrate the feasibility of achieving such compiler def-
inition. It should now only remain for the user to set values for the
static member at their discretion.

-- Scott

Jul 22 '05 #8

P: n/a
Scott J. McCaughrin wrote:
[...]
Yet, note omssion of the term "global" from your citation, which tells me
that the Standard does not require static data members to reside in auto
storage, thus permitting them to reside in static storage as I maintained.
Not permitting. Requiring. Any object declared 'static' has static
storage duration. "Global" usually means "declared/defined in the global
namespace". Static data members are not necessarily defined in the global
namespace. If the class is declared in a namespace other than global, so
will any static data member of that class.
I suspect some of the confusion in this thread may arise from differing
interpretations of that term: "required". You take it to mean whatever
is stipulated by the Standard, while I read it to convey whatever a
compiler was capable of implementing.
The capabilities of the compiler are chanelled by the requirements of the
Standard. In this particular case, the Standard does NOT leave any room
for the compiler to take any initiative WRT where to define the object.
: > But "information hiding" here refers to security against unintended
: > access to private members (static or otherwise). If I have to declare
: > a static member at global level, here is what can happen:
: >
: > Funct array[5];
: > Funct VarArray::funct; // a private static member of VarArray
: >
: > then: array[5] = (Funct)NULL; // unintended access to private member

: What? Huh? What unintended access? This code has _undefined_ behaviour.
: There can be no "intent" here.

Correct, which is why I said "unintended access". The behavior is indeed
"undefined" since alignment and padding considerations (if any) make it
so. But it is the _possibility_ of such access that worries me.
There is always a possibility for undefined behaviour when such constructs
are used. There is very little sense in blaming the language for that.
Since
`array[]' and `funct' are of the same type, it is indeed possible that
the five elements array[0] ... array[4] can immediately precede `funct'
in auto store,
No, not in auto store. In static store.
so that array[5] coincides with `funct' and thereby
allow the spurious overwrite. Now, I readily concede that consigning
the private static member `funct' to static store does not guarantee
safety, but it can lessen the likelihood in cases where the static
store is treated less casually than the stack is. That may be the
best we can ever hope for.
Still, if 'array[5]' is declared at the namespace level right there next
to 'funct', the possibility of undefined behaviour still exists. It is
not up to the language to prevent that.

: > Think about that.

: Nothing to think about. Undefined behaviour is undefined behaviour.
: If you want to convince anybody that there can be something _definite_
: about the code you presented here, sorry, you're mistaken.

But I am not trying to do that: only to show the possibility.
The possibility does _not_ rise from the fact that a member has to be put
into static storage and defined at the namespace level.
Where did
I claim this would "definitely" happen, Victor? Indeed, if there is any
misperception of definiteness at all, it may accrue from use of the term
"private" to suggest that such data members are safe from unwarranted
intrusion, when my example was only submitted to assail that contention.
"private", "protected" are NOT intended to prevent access to underlying
memory by any potentially dangerous means, only by means of C++ code in
a _valid_ C++ program. You give an example of an invalid program and base
your derivations on the possibility that it might cause some unintended
and unwanted effect. Speak about "what if"!

To put these matters into perspective, you may recall that my original
post dealt with the compiler (GNU gpp) complaining about my static data
member as an "undefined reference" (although I suspect it was the linker
complaining). Well, that means that the symbol for my static data member
could not be resolved to any kind of address, i.e., no storage had been
set aside for it, despite my declaration of it in the class as a static.
Not despite. Because of.
Thus, it was treating the symbol like an `extern' (I suspect other
loaders might have even given me "undefined extern" as a more inform-
ative diagnostic).
Yes, essentially.
I do not agree that the user should have to define storage for a class-
level static member separate from its declaration, and so I submitted
my suggestion that -- like any non-class static variable -- it be
allocated in the static store implicity by the compiler when it first
encounters the symbol. Thus the symbol does have a memory address to
satisfy the linker.
But that would be simply impossible. If you include your class definition
with a static data member into more than one translation unit, and at the
same time access that static data member in those translation units, where
does the definition reside? If the compiler will create the definition as
soon as it encounters the declaration, how many definitions is there going
to be?
I only raised the "vtbl" issue by way of showing how the compiler can
automatically define the static data member in static store
(a) Who said that 'vtbl' resides in static store?

(b) There is no 'vtbl' in the standard, which suggests that making static
data members behave similarly to 'vtbl' _may_ unnecessarily limit the
implementations to doing something a certain way. A better example
would be a template. Somehow implementations manage to resolve those
things when they are created in every object module that uses them.
without the
necessity of an explicit definition from the user separate from his/her
delcaration in its class. I am quite sure others can suggest far better
examples to illustrate the feasibility of achieving such compiler def-
inition. It should now only remain for the user to set values for the
static member at their discretion.


And where would they put those values? In the declaration? And what to
prevent them to be different in different translation units?

Yes, if you have a suggestion for fixing this unpleasant trouble with
static data members rising from the fact that they have to be defined in
the namespace separately from the class definition, please do make that
suggestion to comp.std.c++, but you better (a) give proper examples of
what problem you're trying to solve (preventing potential results of
a program with undefined behaviour does not cut it) and (b) be prepared
to answer questions like, "how is it going to work if ..".

At this point, you _don't_ have a problem. You _invent_ one. The fact
that the compiler (or the linker) requires you to define the static data
member is merely _annoying_ (and only to you, I might add), and nothing
to really make a fuss about. That's my point.

V
Jul 22 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.