sizeof

C

CBFalconer

Richard said:
.... snip ...

Don't ask me, ask the people who write such over-clock^tconfid^t
allocating systems, and typically do make one program or another
crash and burn when they run out of over-allocated memory.

When you snip, please snip in units of paragraphs, rather than
isolating a single sentence which is asinine without any context.
Especially if it is me you are snipping.
 
C

CBFalconer

Richard said:
Why does it have to have been mentioned, when providing an example of
how something is possible?


Most operating systems will provide locking such that an implementation
of malloc that just calls the OS for each allocation will appear to be
re-entrant in that you can't make it "go wrong" by calling malloc from
signal handlers. Perhaps you meant to exclude this by adding "truly"
before "re-entrant"?

If you closely examine the first quoted paragraph above (which
happens to have originated with me, but someone removed the
attributions) you will find the phrase "use of suitable concurrency
constructs". Such use does not make a routine re-entrant, it
simply prevents it from being used in a reentrant manner.
 
R

Richard Tobin

Most operating systems will provide locking such that an implementation
of malloc that just calls the OS for each allocation will appear to be
re-entrant in that you can't make it "go wrong" by calling malloc from
signal handlers.
[/QUOTE]
If you closely examine the first quoted paragraph above (which
happens to have originated with me, but someone removed the
attributions) you will find the phrase "use of suitable concurrency
constructs".

Your sentence continued:

I was not referring to threading, but to signal handlers.

In any case, you would need a careful definition of re-entrancy to
support the claim that malloc() cannot be re-entrant. If malloc()
uses a system call, then even if no signal handlers are called while
the system call is in progress, they might be called before malloc()
itself has returned, and malloc() might be safely called again before
the first malloc() has returned.

So your argument becomes "some part of malloc cannot be re-entrant".
In the implement-by-system call case that part is almost the entire
call, but in principle it could probably be as small as one
instruction.

-- Richard
 
E

ena8t8si

CBFalconer said:
Ben said:
Richard Bos wrote:
... snip ...

What would be non-conforming about it? (My guess is that, given
this scenario, it's possible that malloc succeeds [ie: returns a
non-NULL value], but the program fails later when it access this
memory and the O/S discovers "oops, there's really not enough
virtual memory available to allocate".)

Yes. And this is anathema to solid programming and safe computer
systems.

Why should the program fail? This whole scenario is for
multi-process systems, so all that need be done is to have the
program sleep until the actual core is available. All is then
copasetic, remembering that there are no guarantees about speed.

This is sometimes a good approach, but it can cause deadlock.
Suppose you have two processes (two instances of the same process
let's say) that have both allocated huge amounts of memory, and
have both reached line 6 below, and are both waiting for those
100 bytes (there are only 50 bytes left):

Anytime you have concurrent processes contending for resources you
can have deadlocks.

False.

If the concurrent processes are unrestricted in resource use
then there can be deadlock. But a more conservative policy
for doing resource allocation can easily avoid deadlock (and
I don't mean just in trivial ways either).

Excuse my OT post; it bugs me when broad sweeping
statements are made that aren't even approximately correct.
 
C

CBFalconer

CBFalconer wrote:
.... snip ...

False.

If the concurrent processes are unrestricted in resource use
then there can be deadlock. But a more conservative policy
for doing resource allocation can easily avoid deadlock (and
I don't mean just in trivial ways either).

Excuse my OT post; it bugs me when broad sweeping
statements are made that aren't even approximately correct.

Read what I wrote with a modicum of care. Can have does not mean
will have.
 
E

ena8t8si

CBFalconer said:
Read what I wrote with a modicum of care. Can have does not mean
will have.

I did, and I ask you to do the same. There are
well known algorithms for doing resource allocation
that can never deadlock. Standard reading in an
undergraduate OS course.
 
M

Mabden

Joe Wright said:
One of the older and time honored bits of advice to youngsters is "Don't
bother telling Granny how to suck eggs." She knows how. She's been doing
it since before she gave birth to your mother.

Yeah I've heard that saying, but why did Granny do that? Is there a reason
to suck eggs I am not aware of? Is it a sexual methaphore? Who sucks eggs???
Fry them in a little butter for a delicious treat, but sucking raw eggs?
Granny was nasty!

-Mabden
 
M

Mark McIntyre

Yeah I've heard that saying, but why did Granny do that? Is there a reason
to suck eggs I am not aware of? Is it a sexual methaphore?

is that some sort of meths-based perfume? :)
Who sucks eggs???
Fry them in a little butter for a delicious treat, but sucking raw eggs?

Excellent source of protein actually.
Granny was nasty!

/Your/ granny maybe....

gd&r
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
A

Ancient_Hacker

Hi,
How can we write a function, which functionality is similar to sizeof
function
any one send me source code
Reddy

Depends on how sloppy the answer can be.

In the strictest sense, you *cant* write sizeof any other way. That's
because sizeof ISNT like anything else in C. It may look like a
function as most people put parentheses around its operand. But it's
not really a function, it's something more primitive, much like a unary
operator like minus or not.

You see, sizeof can take any expression or type as an argement.
Nowhere else in C (I think) can you put either a variable or type in
the same place without serious syntax errors.

But sizeof is special, as you sometimes would like to know the size of
a type, like sizeof unsigned long int, and sometimes you want to know
the size of a variable, like sizeof FILE.

Now there are several half-arsed ways of doing a sizeof(type) using
macros:

unsigned long int Size;

#define PutSizeofTypeIntoSize(t) { t a,b; Size=b-a; } // notice it
returns size in a global!

..


and several half-arsed ways of doing a sizeof(var) using macros,
something like:

unsigned long int Size;

#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; } // notice it
returns size in a global!


But IN GENERAL, you might want to say sizeof( a + b ) or sizeof( main
), and I dont hinnk you can write a macro that will do that. Oh, and
BTW, sieof DOESNT EVALUATE it's argument, unlike anywhere else in C.
it does parse the argument, and go through most of the folderol of
evaluating it, everything but generating code to do so. You see sizeof
happens at compile-time, not at run-time.

Hope this gives you a glimmer of what's going on.
 
F

Flash Gordon

Ancient_Hacker said:
Depends on how sloppy the answer can be.

In the strictest sense, you *cant* write sizeof any other way. That's
because sizeof ISNT like anything else in C. It may look like a
function as most people put parentheses around its operand. But it's
not really a function, it's something more primitive, much like a unary
operator like minus or not.

True enough. It *is* a unary operator, rather than being "much like" one.
You see, sizeof can take any expression or type as an argement.
Nowhere else in C (I think) can you put either a variable or type in
the same place without serious syntax errors.

#define VAR_OR_TYPE(x)
VAR_OR_TYPE(int)
int x;
VAR_OR_TYPE(x)

A bit contrived though ;-)
But sizeof is special, as you sometimes would like to know the size of
a type, like sizeof unsigned long int, and sometimes you want to know
the size of a variable, like sizeof FILE.

Now there are several half-arsed ways of doing a sizeof(type) using
macros:

and *none* of them are any good.
unsigned long int Size;

#define PutSizeofTypeIntoSize(t) { t a,b; Size=b-a; } // notice it
returns size in a global!

That is just completely wrong.
and several half-arsed ways of doing a sizeof(var) using macros,
something like:

unsigned long int Size;

#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; } // notice it
returns size in a global!

The above will always set Size to 1.
But IN GENERAL, you might want to say sizeof( a + b ) or sizeof( main
), and I dont hinnk you can write a macro that will do that. Oh, and
BTW, sieof DOESNT EVALUATE it's argument, unlike anywhere else in C.
it does parse the argument, and go through most of the folderol of
evaluating it, everything but generating code to do so. You see sizeof
happens at compile-time, not at run-time.

Hope this gives you a glimmer of what's going on.

I doubt it will give much insite, since your example where fundamentally
floored.

There is a very good reason for sizeof being an operator in C, even
ignoring your glaring errors it is not possible to write an equivalent
to sizeof in portable C.
 
A

Ancient_Hacker

Flash said:
True enough. It *is* a unary operator, rather than being "much like" one.

Well, seeing as it's unlike every other unary operator in a very basic
way, I stick with my story.


That is just completely wrong.

A tad harsh. I was sitting out on the deck having my morning coffee
and didnt have a C compiler on the laptop. Now that I do, I see I
forgot some very necessary fribbles and frobs. Try this:

#define PutSizeofTypeIntoSize(t) { t a,b; Size=((char *)&a)-((char
*)&b); }



unsigned long int Size;

#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; } // notice it
returns size in a global!

The above will always set Size to 1.

Well, we're both wrong. It always returns the size of an ELEMENT of V,
if V is of type array. It's a syntax error if the variable isnt an
array.

I doubt it will give much insite, since your example where fundamentally
floored.

insite : hows about "insight"
where: hows about "were"
floored: hows about "flawed"
 
C

Chris Dollin

Ancient_Hacker said:
A tad harsh. I was sitting out on the deck having my morning coffee
and didnt have a C compiler on the laptop. Now that I do, I see I
forgot some very necessary fribbles and frobs. Try this:

#define PutSizeofTypeIntoSize(t) { t a,b; Size=((char *)&a)-((char
*)&b); }

There's rather a strong reliance there on the compiler allocating
objects in just the right order & packing.
insite : hows about "insight"
where: hows about "were"
floored: hows about "flawed"

How's about "how's"?
 
F

Flash Gordon

Ancient_Hacker said:
Well, seeing as it's unlike every other unary operator in a very basic
way, I stick with my story.

It takes one operand and produces one value. Where is the difference?
A tad harsh. I was sitting out on the deck having my morning coffee
and didnt have a C compiler on the laptop. Now that I do, I see I
forgot some very necessary fribbles and frobs. Try this:

#define PutSizeofTypeIntoSize(t) { t a,b; Size=((char *)&a)-((char
*)&b); }

Still fundamentally broken. The compiler is not obliged to place a and b
next to each other in memory nor to put them in any particular order. In
any case, subtracting pointers to different objects is undefined.
unsigned long int Size;

#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; } // notice it
returns size in a global!
The above will always set Size to 1.

Well, we're both wrong. It always returns the size of an ELEMENT of V,
if V is of type array. It's a syntax error if the variable isnt an
array.

I failed to read it carefully enough. However, if the parameter is of
array type it sets Size to 1.
markg@markgordon-lp ~
$ cat t.c
#include <stdio.h>
#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; }
int main(void)
{
int Size,t[4];
PutSizeofVarIntoSize(t);
printf("%d\n",Size);
return 0;
}


markg@markgordon-lp ~
$ gcc -ansi -pedantic t.c

markg@markgordon-lp ~
$ ./a.exe
1

markg@markgordon-lp ~

So for the instances where it does not produce a syntax error what I
stated is true. What you stated is *never* true.
insite : hows about "insight"
where: hows about "were"
floored: hows about "flawed"

Feel free to complain about a dyslexic making spelling errors if you
want, it still does not make the code you posted any better. It is still
fundamentally flawed.
 
A

Ancient_Hacker

Flash said:
Still fundamentally broken. The compiler is not obliged to place a and b
next to each other in memory nor to put them in any particular order. In
any case, subtracting pointers to different objects is undefined.

I guess from an ivory-tower perspective you're right.

In the real world, you might be mildly interested to learn that
compilers usually place variables next to each other. Has on every
compiler I've ever tried, let's see: Unix v7 C on a 11/34, Borland C
since version 1.0, Microsoft C since 1985 IIRC, Sun C since 1985, SGI C
since 1997, gnu C since about forever. I'd love to hear of a single
counter-example. BTW I could fix that problem by declaring the vars
in a struct.

unsigned long int Size;

#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; } // notice it
returns size in a global!
The above will always set Size to 1.

Well, we're both wrong. It always returns the size of an ELEMENT of V,
if V is of type array. It's a syntax error if the variable isnt an
array.

I failed to read it carefully enough. However, if the parameter is of
array type it sets Size to 1.

Well, here with Microsoft Visual C 2005, it returns 4 or a syntax
error. Guess it's implementation dependent?
So for the instances where it does not produce a syntax error what I
stated is true. What you stated is *never* true.

See above.

Feel free to complain about a dyslexic making spelling errors if you
want,

Those can't be dyslexic or spelling errors. They're just the wrong
words.

it still does not make the code you posted any better. It is still
fundamentally flawed.


Well, that fundementally flawed code has been running in a Web app
since 1997, serving up about 50,000 pages a day. And in about 200,000
client-side apps.

..
 
B

Ben Pfaff

Ancient_Hacker said:
In the real world, you might be mildly interested to learn that
compilers usually place variables next to each other. Has on every
compiler I've ever tried, let's see: Unix v7 C on a 11/34, Borland C
since version 1.0, Microsoft C since 1985 IIRC, Sun C since 1985, SGI C
since 1997, gnu C since about forever. I'd love to hear of a single
counter-example.

Some compilers pack small objects, e.g. short or char objects,
next to one another, so that they can save space (due to
alignment requirements). If you have
short a;
int b;
short c;
then `a' and `c' might be placed next to one another.
BTW I could fix that problem by declaring the vars in a struct.

You'd still have the problem of padding between struct members.

(Why not just use the sizeof operator? That's what it's for.)
 
R

Richard Heathfield

Ancient_Hacker said:
I guess from an ivory-tower perspective you're right.

In the real world, you might be mildly interested to learn that
compilers usually place variables next to each other. Has on every
compiler I've ever tried, let's see: Unix v7 C on a 11/34, Borland C
since version 1.0, Microsoft C since 1985 IIRC, Sun C since 1985, SGI C
since 1997, gnu C since about forever. I'd love to hear of a single
counter-example.

Ah, I see we're back to "all the world's compilers are the same as the ones
I've used". The world is bigger than that. Counter-examples may exist or
they may not - I don't know, since I never bothered to find out, because my
programs don't rely on such nonsense - but even if no counter-example
exists today, one might be released tomorrow.
BTW I could fix that problem by declaring the vars in a struct.
Wrong.
unsigned long int Size;

#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; } // notice it
returns size in a global!
The above will always set Size to 1.

Well, we're both wrong. It always returns the size of an ELEMENT of V,
if V is of type array. It's a syntax error if the variable isnt an
array.

I failed to read it carefully enough. However, if the parameter is of
array type it sets Size to 1.

Well, here with Microsoft Visual C 2005, it returns 4 or a syntax
error. Guess it's implementation dependent?

No, it's required to evaluate to 1 if v has pointer type or array type. So
you appear to be claiming Visual C is non-conforming.

<snip>
 
W

Walter Roberson

Ancient_Hacker said:
In the real world, you might be mildly interested to learn that
compilers usually place variables next to each other. Has on every
compiler I've ever tried, let's see: Unix v7 C on a 11/34, Borland C
since version 1.0, Microsoft C since 1985 IIRC, Sun C since 1985, SGI C
since 1997, gnu C since about forever. I'd love to hear of a single
counter-example.

Counter-examples from SGI C:

1) -ivpad Improves cache behavior by causing the linker to perform
intervariable padding of some large variables. This is in
effect by default. (C, C++, F77, F90)

2) -LD_LAYOUT:
multigot
This is for internal use. Usually, the linker attempts
to link everything, generating a single GOT. If this
fails, it reruns the layout phase and possibly creates
multiple GOT regions. This option causes the first
layout pass to fail. This is used in conjunction with
the mgot_threshold option described previously.

(GOT is Global Offset Table, and the relevance here is that when
procedure variables are large enough that they cannot all be completely
addressed by a single address register together with a standard-width
relative offset, then the linker will split the space to use multiple
address registers, in which case syntactically adjacent variables
will not necessarily be adjacent in addresses.)

3) -LD_LAYOUT:
reorder_file=feedback_file
Names a feedback file. When specified, function layout
in the text section is optimized to minimize page
faults and I-cache misses based upon the frequency
information in feedback_file. This file is usually
produced by prof(1)/cvperf(1) or sscord(1)/ssorder(1),
but a user can also construct or modify this ASCII
file.

4) initialized static or extern variables are not usually placed adjacent
to uninitialized static or extern variables, because the uninitialized
globals and statics are handled through a "demand-zero page" (a hardware
mechanism that automatically initializes a memory page to 0 when
it is allocated and given to a process.) Initialized variables have
to have their initial value read from the object file (which might
not happen until the first reference to the virtual memory page,
as SGI IRIX can postpone loading in code, constants, and
globals and statics, reading them from the object file when needed
[and for code and constants, instead of copying them to a disk swap file,
IRIX can just drop the virtual descriptor, leading the values to be
reloaded from the object file if they turn out to be needed later.]
 
F

Flash Gordon

Ancient_Hacker said:
I guess from an ivory-tower perspective you're right.

In the real world, you might be mildly interested to learn that
compilers usually place variables next to each other. Has on every
compiler I've ever tried, let's see: Unix v7 C on a 11/34, Borland C
since version 1.0, Microsoft C since 1985 IIRC, Sun C since 1985, SGI C
since 1997, gnu C since about forever. I'd love to hear of a single
counter-example.

Given the right patches and correct options gcc *will* rearrange
variables. I don't know whether it would swap them in the specific
instance given, but there is no reason for anyone to make sure it
doesn't. As to counter example:
markg@home ~ $ gcc -ansi -pedantic -O3 t.c
markg@home ~ $ ./a.out
1
4
-4
markg@home ~ $ gcc --version
gcc (GCC) 4.1.1 (Gentoo 4.1.1)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

markg@home ~ $ cat t.c
#include <stdio.h>
#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; }
#define PutSizeofTypeIntoSize(t) { t a,b; Size=((char *)&a)-((char
*)&b); }
int main(void)
{
int Size,t[4];
PutSizeofVarIntoSize(t)
printf("%d\n",Size);
PutSizeofTypeIntoSize(char)
printf("%d\n",Size);
PutSizeofTypeIntoSize(int)
printf("%d\n",Size);
return 0;

}

So both of your macros have failed on a *real* system.
> BTW I could fix that problem by declaring the vars
in a struct.

Then you potentially hit problems with padding.
unsigned long int Size;

#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; } // notice it
returns size in a global!
The above will always set Size to 1.
Well, we're both wrong. It always returns the size of an ELEMENT of V,
if V is of type array. It's a syntax error if the variable isnt an
array.
I failed to read it carefully enough. However, if the parameter is of
array type it sets Size to 1.

Well, here with Microsoft Visual C 2005, it returns 4 or a syntax
error. Guess it's implementation dependent?

Nope, I guess you didn't post the code I provided. I built in on Visual
Studio 2005 and I got 1, just as the standard requires. Here is the code
again.
#include <stdio.h>
#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; }
int main(void)
{
int Size,t[4];
PutSizeofVarIntoSize(t);
printf("%d\n",Size);
return 0;

}

With the code other set of code I've posted further above I get
1
0
0

This I think is actually wrong.

However, this all just further demonstrates how bad your suggestions are.
See above.
Nope.


Those can't be dyslexic or spelling errors. They're just the wrong
words.

Since I am a dyslexic, and have read up on the topic, I have a
reasonable idea about the types of mistakes dyslexic make.
it still does not make the code you posted any better. It is still

Well, that fundementally flawed code has been running in a Web app
since 1997, serving up about 50,000 pages a day. And in about 200,000
client-side apps.

I just hope that I don't use any code you've had anything to do with.
I've tried both your macros and keep finding systems on which they
demonstrably fail and they are completely pointless since sizeof exists.
Personally I would reject any candidate who thought that using a macro
such as you have show was ever a good idea. That reminds me, I have a CV
to check for a C programming position.
 
F

Flash Gordon

Richard said:
Ancient_Hacker said:


Ah, I see we're back to "all the world's compilers are the same as the ones
I've used". The world is bigger than that. Counter-examples may exist or
they may not - I don't know, since I never bothered to find out, because my
programs don't rely on such nonsense - but even if no counter-example
exists today, one might be released tomorrow.

Fortunately I only had to try one of my compilers to find a counter
example. I can even change the results by changing the optimisation
level on the compiler. Strangely enough, the second system I tried, AIX
5.3 using gcc, also failed. I guess on some systems they tend to
allocate things the opposite way around to the order generally used on
x86 based systems :)
BTW I could fix that problem by declaring the vars in a struct.
Wrong.
unsigned long int Size;

#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; } // notice it
returns size in a global!
The above will always set Size to 1.
Well, we're both wrong. It always returns the size of an ELEMENT of V,
if V is of type array. It's a syntax error if the variable isnt an
array.
I failed to read it carefully enough. However, if the parameter is of
array type it sets Size to 1.
Well, here with Microsoft Visual C 2005, it returns 4 or a syntax
error. Guess it's implementation dependent?

No, it's required to evaluate to 1 if v has pointer type or array type. So
you appear to be claiming Visual C is non-conforming.

I claim it is conforming by default and Ancient_Hacker is wrong, since
it produced 1 when I tried it on MSVC 2005. Sometimes having an MSDN
subscription is useful :)
 
K

Keith Thompson

Ancient_Hacker said:
I guess from an ivory-tower perspective you're right.

In the real world, you might be mildly interested to learn that
compilers usually place variables next to each other. Has on every
compiler I've ever tried, let's see: Unix v7 C on a 11/34, Borland C
since version 1.0, Microsoft C since 1985 IIRC, Sun C since 1985, SGI C
since 1997, gnu C since about forever. I'd love to hear of a single
counter-example. BTW I could fix that problem by declaring the vars
in a struct.

You're not just assuming that the variables are adjacent; you're also
assuming that the second declared variable has a higher address than
the first. It may well be that that's true for most or all existing
implementations. I don't know about that. What I do know is that
there is absolutely no such guarantee in the standard, and there's no
need to write code that depends on such behavior.
unsigned long int Size;

#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; } // notice it
returns size in a global!
The above will always set Size to 1.

Well, we're both wrong. It always returns the size of an ELEMENT of V,
if V is of type array. It's a syntax error if the variable isnt an
array.

I failed to read it carefully enough. However, if the parameter is of
array type it sets Size to 1.

Well, here with Microsoft Visual C 2005, it returns 4 or a syntax
error. Guess it's implementation dependent?

I find that very surprising. Here's a small program that uses your
macro:
================================
#include <stdio.h>

#define PutSizeofVarIntoSize(v) { Size= &v[1]-&v[0]; }

int main(void)
{
size_t Size;
double arr[10];
PutSizeofVarIntoSize(arr)
printf("Size = %d\n", (int)Size);
return 0;
}
================================

When I compile and execute it, it prints "Size = 1". Try it with MSVC
2005, and lets us know what it prints. Or show us some complete
program using your macro, as you posted it, that demonstrates it
setting Size to any value other than 1. (Or admit that you've made a
mistake.)

An aside: That's not the best way to write a statement-like macro.
Note that there's no semicolon after the call; I could have added one,
but it would have created an empty statement. Question 10.4 in the
comp.lang.c FAQ, <http://www.c-faq.com/>, describes how to write a
multi-statement macro.

Since your macro only has one statement, and it's an expression
statement at that, it would be better written as:

#define PutSizeofVarIntoSize(v) (Size = &(v)[1] - &(v)[0])

or, for that matter:

#define GetSizeofVar(v) (&(v)[1] - &(v)[0])

which still doesn't work, but it's a much cleaner macro definition.

Well, it's true for an array of some character type, but that's
correct only in the sense that a stopped clock is right twice a day.

[...]
it still does not make the code you posted any better. It is still


Well, that fundementally flawed code has been running in a Web app
since 1997, serving up about 50,000 pages a day. And in about 200,000
client-side apps.

Great. How many different platforms has it been running on? If a
piece of code is horribly and gratuitously non-portable, but happens
to work on a single platform, it will continue to work indefinitely on
that single platform, and perhaps on others as well. Running it
millions of times over several years proves nothing.
 

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
474,184
Messages
2,570,979
Members
47,579
Latest member
CharaS3188

Latest Threads

Top