Is this a good habit?

M

Mark McIntyre

No, you don't. Otherwise you would have mentioned it. What you diod
instead is give an example of something completely different:

Excellent, so now you are attacking one of /the/ most respected
posters here. Top marks for idiocy.

Expect to get rapidly plonked by those with short fuses, and your
every post watched like a hawk by those with a strong sense of duty to
the newbies, who do not deserve to be fed misinformation.
hat case has nothing to do with BSS storage. In your case the compiler
had to generate INITIALIZED data,

You were claiming that no compiler would be so stupid as to fail to
make obvious optimisations. Chris (and others) have produced
counterexamples of even more obvious optimisations that got missed.

For what its worth, I recall one of the earlier MSC implementations
(possibly 5.1) did indeed insert zero-initialised storage into the
binary. After all, if it had been part-initialised to nonzeros then
creating it from scratch could have been expensive at runtime.

Please feel free to start straightening me out. Any time now.

Its happening.
I do get a bit miffed by folks that are consistently intellectually
dishonest.

Do you find yourself doing Travis Bickle impersonations a lot?
Some people go to great lengths to ignore reality and hold to very
narrow views. I've found those attitudes to be unhelpful.

Indeed.
--
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

Mark said:
Chris said:
You were claiming that no compiler would be so stupid as to fail to
make obvious optimisations. Chris (and others) have produced
counterexamples of even more obvious optimisations that got missed.

Uh, no. First of all, incrementing a BSS counter to allocate
uninitialized data is about the only rational way to do it. It's not
an optimization. And I said no such thing. It's hard to be a
revisionist historian when the original words are jsut a click away.

Chris's example, while interesting in a theoretical and historical
sense, has nothing at all to do with what we were discussing. case
tables are initialized data, or code-- not anything we were discussing
at all. And optimizing that is not obvious, I recall the UCSD
compiler had the same inefficiency, (until I fixed it so it would
generate value/jmp address pair tables when appropriate).

For what its worth, I recall one of the earlier MSC implementations
(possibly 5.1) did indeed insert zero-initialised storage into the
binary. After all, if it had been part-initialised to nonzeros then
creating it from scratch could have been expensive at runtime.

You're still not getting the big distinction between initialized data
and uninitialized data. The former has to be pretty much emitted as is
(with some obvious compressions possible). global variables that do
not have the "= something" business are a whole different kettle of
fish. All the compiler has to do is define a label and bump a BSS
size variable.

For a little more insight-- the whole BSS segment business goes back to
the IBM 7090 days, when memory cost a dollar a word or more. There was
no place for the system loader to sit when loading a big program, so
some smart fellow suggested that assemblers and compilers explicitly
point out what areas of memory did not have to be initialized. The
loader would relocate itself into that space and merrily load the
program code and data around it. Nowadays we have the luxury of lots
of memory so BSS space isnt that crucial as it once was, but it still
helps cut down the size of executables.
 
R

Richard Heathfield

Ancient_Hacker said:
Richard said:
int a[1000000];

Stop right there. No implementation is obliged to support an object that
size.

Thanks once again for the disengenuous comeback.

Nothing disingenuous about it at all. You posted a program that the C spec
doesn't require an implementation to be able to support.
One might surmise that you know the purpose, or actually, purposes of
my typing 1 million in that spot.

Presumably you were trying to write an invalid program. You succeeded on
several counts. I merely identified the first problem.
 
R

Richard Heathfield

Keith Thompson said:

Not all code needs to worry about being used in a multithreading
environment.

Nevertheless, avoiding static objects is a reasonable rule of thumb, unles
they're also const.
 
C

Chris Torek

Ancient_Hacker said:
I don't recall a one [C compiler, including pre-ANSI] that emitted
long chunks of zeroes when it didnt have to.

No, you don't. Otherwise you would have mentioned it.

What on earth makes you think that? It is hardly relevant, since
it is no longer a useful C compiler and was never ANSI-conformant.

(In any case, I take it you never used Turbo C.)

You might also look at:

http://www.digitalmars.com/d/archives/c++/dos/32-bits/38.html

(where Walter Bright does say that this is a bug, not a feature;
and of course this is C++, not C).
What you did instead is give an example of something completely
different:

Not *completely* different at all -- just another case of a compiler
doing something stupid.
 
J

J. J. Farrell

Snis said:
EventHelix.com said:
Snis Pilbor wrote:
It seems pretty common to return pointers to a static array, for
example:

char *capitalize( char *name ) {
static char buf[MAX_STRING_LENGTH];
sprintf( buf, "%s", name );
if ( *buf >= 'a' && *buf <= 'z' )
*buf += 'A' - 'a';
return buf;
}

IMHO, Use of static variables inside functions is not a good idea. You
will end up with code that is not thread safe. The function will
misbehave if multiple concurrently running threads are invoking the
function with static variables.

Yes, of course, it goes without saying in either case one must exercise
caution.
IMHO one of the most beautiful things about C is that it allows you
such flexibility. It does not assume you are a baby and hold your
hand.
If I wanted a language where various people told me "Oh you can't do
that, it's too dangerous", I would program Java =) Thanks for the word
of warning anyway, though.

What the hell is *WRONG* with you people. Review what EventHelix is
saying. If you need to run in a multithreaded environment then static
solution *CANNOT WORK*. Let me repeat: *CANNOT WORK*.

So you take this piece of information and you go on some diatribe about
how you are so grateful for the fact that C lets you code things that
in some contexts *CANNOT WORK*?

Of course it can work, and it works correctly in many programs. It
cannot work if more than one thread need to concurrently do the quantum
of 'call the function and use the results'. If the design of the
program prevents that happening, or if an associated mutex is required
to be held before using the function, then it works correctly.

Whether it's the best or optimum way to do it is another question, and
I'd almost always say it's not. But as Snis says, C has the flexibility
to allow it to be done this way if it is appropriate for whatever
reason. Most of the times I've found it appropriate are when a library
of such code already exists, and its functionality is now needed in a
limited and controlled way in a threaded program.
Really? Unless the static is read-only, or you are in the module
containing main(), I would never do this -- because I figure I am
"smart enough" to know better.

So you would do it sometimes even though it *CANNOT WORK*?
If you want to avoid the allocation
costs, then you can *pass in* the buffers you want to be used -- in
that way you retain the performance, and there is no multithreading
issue. Its a question of scalability -- if you need to think hard
about every piece of code you use (in this case knowing that you can't
use the function while multithreading), then that's time and energy
taken away from thinking hard about other programming details, like
architecture/design.

Indeed, and that's the main issue to trade off in my opinion. C gives
you the flexibility to do it the static way if the advantages are big
enough.
I'm not sure this occurred to K&R (and T) when they originally designed
C and Unix (the counter evidence in the std library seems overwhelming)
but what you should celebrate is that they don't *force* you to make
this kind of mistake. I guess its a moot point since you *are* making
the mistake anyways.

The original C model didn't have the concept of multiple threads in a
single address space, since it was based on the original UNIX concept
of forked processes with private address space.
 
I

Ian Collins

C and quite a bit of most networking libraries based on the original BSD
interface.
Of course it can work, and it works correctly in many programs. It
cannot work if more than one thread need to concurrently do the quantum
of 'call the function and use the results'. If the design of the
program prevents that happening, or if an associated mutex is required
to be held before using the function, then it works correctly.



The original C model didn't have the concept of multiple threads in a
single address space, since it was based on the original UNIX concept
of forked processes with private address space.
The same problem exists with the UNIX standard library functions that
use internal static buffers.

Even today, people still use these calls even though they have been
superseded by thread safe replacements.
 
C

Chris Dollin

Chris said:
Indeed. (I believe ARM had an interesting paging-specific compressed
binary format.)

I don't know if this is what you're thinking of, but RISC OS (hence on the
ARM) did indeed have a executable file format that as it loaded (or
perhaps after it had loaded) it uncompressed code from the file. The win
was of course that it could uncompress much faster than it could load
from disc (and it made the disc files smaller, a not inconsiderable gain
in those days).

I don't remember it being paging-specific, though. Maybe that was on
ARM Linux.
 
G

gw7rib

Eric said:
Snis Pilbor wrote:
[snip]
char *capitalize( char *name )
{
static char *buf;

if ( !buf )
{
buf = malloc( MAX_STRING_LENGTH );
if ( !buf ) return name;

Whoa, Nellie! If returning the unmodified original is an
acceptable outcome, why bother writing the function at all?

That said, it's the most graceful handling of a failed malloc that I
have seen for a long time. It depends what your priorities are.
 
M

Michael Wojcik

What the hell is *WRONG* with you people.

We know how to think.
Review what EventHelix is
saying. If you need to run in a multithreaded environment then static
solution *CANNOT WORK*. Let me repeat: *CANNOT WORK*.

Really? How odd, as I have numerous counterexamples in code that's
used every day. Of course, the callers of such functions have to
exercise some caution, but it works with no problems whatsoever.

This may come as a surprise to you, Paul, but there are techniques
for managing shared resources in concurrent environments.
 
M

Michael Wojcik

We've been over this before.

And you still haven't learned.
I've been saddled with using C since the
very early days, so it's been my misfortune to intimately know
[a pointless list of implementations].

How nice for you. Many of us here - myself included - could present
similarly long lists. They would be equally irrelevant.

Either you believe a handful of C implementations constitutes "most"
such implementations, in which case I'm afraid you're mistaken; or
you're attempting to support your claims with arguments you know to
be bogus, which does nothing to impress those of us who know better.
 
E

Ed Prochak

J. J. Farrell wrote:
[]
Of course it can work, and it works correctly in many programs. It
cannot work if more than one thread need to concurrently do the quantum
of 'call the function and use the results'. If the design of the
program prevents that happening, or if an associated mutex is required
to be held before using the function, then it works correctly.

as another poster noted it doesn't take threads to make it unsafe.
(the example given was a printf() like:
printf("%s %s\n",capitalize(firstname),capitalize(lastname) );
Whether it's the best or optimum way to do it is another question, and
I'd almost always say it's not. But as Snis says, C has the flexibility
to allow it to be done this way if it is appropriate for whatever
reason. Most of the times I've found it appropriate are when a library
of such code already exists, and its functionality is now needed in a
limited and controlled way in a threaded program.

I agree, it is not a generally safe way to deal with this problem.

[]
The original C model didn't have the concept of multiple threads in a
single address space, since it was based on the original UNIX concept
of forked processes with private address space.

But the problem is not limited to multiple threads.

Ed
 
M

Mark McIntyre

I'd consider CDC 6600's, 7600's, Vax 11/780's (Which was definitely a
mainframe, at least in size) as "mainframes".

Bizarre. The 11/780 is quite definitely a mini.

--
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
 
M

Mark McIntyre

You're still not getting the big distinction between initialized data
and uninitialized data.

/I/ am, but I don't think you are. Automatics (which are the only sort
that /can/ be uninitialised) are created at runtime, generally on the
stack or maybe in registers if small enough.

You seem to be talking about file-scope variable,s which /are/
initialised, even if not explicitly.
global variables that do
not have the "= something" business are a whole different kettle of
fish. All the compiler has to do is define a label and bump a BSS
size variable.

Er, these /must/ be initialised. The language spec requires it.
For a little more insight-- the whole BSS segment business goes back to
the IBM 7090 days,

This is of course quite offtopic, and quoting reams of stuff I can
read for myself on wikipedia (yuck) or in any of the myriad books on
my shelves won't win you any brownie points.
--
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

Mark said:
Bizarre. The 11/780 is quite definitely a mini.

Well, opinions will differ, but IMHO anything that is four racks wide,
needs special power hookup, needs lots of airconditioning, is placed in
a raised-floor computer room, costs over $150K, has its own
minicomputer built-in as a boot and diagnostic device, has tape drives
and line printers attached, has an operator assigned to run it, falls
into the (low end) of the "mainframe" category.

True, the Vax line eventually would be squeezed into little beige
shoeboxes, but the original 780 took several trips with a forklift to
move.
 
A

Ancient_Hacker

Mark said:
On 27 Jul 2006 15:10:23 -0700, in comp.lang.c , "Ancient_Hacker"


/I/ am, but I don't think you are. Automatics (which are the only sort
that /can/ be uninitialised) are created at runtime, generally on the
stack or maybe in registers if small enough.

You seem to be talking about file-scope variable,s which /are/
initialised, even if not explicitly.

Ah, I now see where we diverged. Yes, file scope variables are set to
zero,
but in all the compilers I've worked with, which as a rough guess would
cover about 77% of all the binaries ever generated, there's a little
snippet of code in the C startup code that initializes them to zero.
As differentiated from the compiler having explicitly output enough
binary zeroes to fill up the variables. As most computers can zero
memory a few decades faster than they can read zeroes off a disk, it's
a win-win situation-- smaller executables and faster program startup.

..
Er, these /must/ be initialised. The language spec requires it.

yes, as explained above, by the C startup code.
 
F

Flash Gordon

Ancient_Hacker said:
Ah, I now see where we diverged. Yes, file scope variables are set to
zero,
but in all the compilers I've worked with, which as a rough guess would
cover about 77% of all the binaries ever generated, there's a little

From the list you've given in the past, I doubt it. I've not listed any
C compilers targeting embedded system (I bet you have never heard of the
TMS320C25 nor the TMS320C80), you don't seem to have done any targeting
the PPC, not the 68000, not the Z80, nor lots of others.
snippet of code in the C startup code that initializes them to zero.
As differentiated from the compiler having explicitly output enough
binary zeroes to fill up the variables. As most computers can zero
memory a few decades faster than they can read zeroes off a disk, it's
a win-win situation-- smaller executables and faster program startup.

That's as maybe. However, most of us here don't claim to have
encountered the majority of implementations.
 
A

Ancient_Hacker

Flash said:
From the list you've given in the past, I doubt it. I've not listed any
C compilers targeting embedded system (I bet you have never heard of the
TMS320C25 nor the TMS320C80), you don't seem to have done any targeting
the PPC, not the 68000, not the Z80, nor lots of others.

Oh, I just got tired recollecting. Lesse: Apple MPW C for the 68000
and PPC,
then CodeWarrior C for PPC, then Microsoft and Borland C, but I already
listed those, then WATCOM C, then Microchip C for the PIC16x series,
then TI C for the 32x series (in a cochlear implant), then Some
godawful C Motorola recommended for the DSP56xxx series (outside CPU
for cochlear implant), before that, Symantec (Urp) C and gcc for the
program that drove the 56000. For all of the latter ones the program
and data had to fit into a 1 or 2 Megabyte flash ROM, and the data had
to fit at run time in the on-chip 64K fast RAM, so you can be sure we
scoured the link map looking for dumb allocations.

That's as maybe. However, most of us here don't claim to have
encountered the majority of implementations.

Well I guess it depends how you count them: by implementations or by
programming seats. I havent done a marketing survey, but just by
weighing the questions on the internet, I suspect the ones I've
listed above cover at least 80% of the seats. Just gcc and Microsoft
Visual C prolly cover 75%. I'd love to see some actual figures.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top