Why C is really a bad programming language

G

Guest

|> (e-mail address removed) writes:
|>>>
|>>> C does not mandate the use of 32-bit integers for time_t.
|>>> This is truly an implementation issue, and the fix is so easy that
|>>> implementors have no excuse for not fixing the problem right now.
|>>
|>> Binary compatibility with existing code seems like a pretty good excuse
|>> to me.
|>
|> Precisely which binary interfaces did you have in mind?
|
| One is the binary interface between a program and a dynamically linked
| C library, like say the time function.

C does not have binary interfaces. Architectures do. They are just a
form of subset of an architecture. If you switch to a new ABI, such as
using 64 bits for time_t or off_t, then use another library. You can
have 2 or more libraries on a system, and link programs to specific ones.


| But dynamic liking technology has now advanced into the 1970's,
| at least on some operating systems. It's possible for a shared
| library to expose a compatible time function for old binary clients,
| one with a 32 bit time_t, and a 64 bit time function for new clients.

No need. Link to the proper library.


| Of course, programs that aren't going to be recompiled will stay broken.
| That's a given. But fixes to the interface don't have to be held back
| for the sake of these programs.

No. They just stay linked to a library providing a legacy ABI.
 
G

Guest

| Phil Carmody wrote:
|> (e-mail address removed) writes:
|>>> C does not mandate the use of 32-bit integers for time_t.
|>>> This is truly an implementation issue, and the fix is so easy that
|>>> implementors have no excuse for not fixing the problem right now.
|>> Binary compatibility with existing code seems like a pretty good excuse
|>> to me.
|>
|> Precisely which binary interfaces did you have in mind?
|
| Those which use time_t.

In what ABI?
 
G

Guest

| (e-mail address removed) wrote:
|>> C does not mandate the use of 32-bit integers for time_t.
|>> This is truly an implementation issue, and the fix is so easy that
|>> implementors have no excuse for not fixing the problem right now.
|>
|> Binary compatibility with existing code seems like a pretty good excuse
|> to me.
|
| Sooner or later the binaries that it is incompatible with will have to
| be recompiled with a newer library if possible, or discarded if
| necessary. The sooner this happens, the better for everyone (except, of
| course, whoever it is that has to do the recompile or replace the
| discarded binary). As long as a backwards compatibility option is
| provided (it could even be the default, at least for the next decade or
| so), this shouldn't be a serious problem.

It does not need to be recompiled. The system just needs to keep a legacy
library for the old ABI, and use a new library for a new ABI (ABI's might
differ in just a few things like size of time_t and off_t).

FYI, the whole mess with 64 bit file offsets was done all wrong. It should
have simply been a new ABI that has a slightly different library name.
Keep both libraries where legacy binaries exist. All recompiles would by
default use the new ABI definitions.
 
J

James Kuyper

| Phil Carmody wrote:
|> (e-mail address removed) writes:
|>>> C does not mandate the use of 32-bit integers for time_t.
|>>> This is truly an implementation issue, and the fix is so easy that
|>>> implementors have no excuse for not fixing the problem right now.
|>> Binary compatibility with existing code seems like a pretty good excuse
|>> to me.
|>
|> Precisely which binary interfaces did you have in mind?
|
| Those which use time_t.

In what ABI?

I would assume, all of them, though I could be mistaken.

Do you know of any ABI where modules which communicate with each other
using time_t would remain binary compatible with each other if compiled
by compilers with different ideas of the size of time_t?
 
J

James Kuyper

| (e-mail address removed) wrote:
|>> C does not mandate the use of 32-bit integers for time_t.
|>> This is truly an implementation issue, and the fix is so easy that
|>> implementors have no excuse for not fixing the problem right now.
|>
|> Binary compatibility with existing code seems like a pretty good excuse
|> to me.
|
| Sooner or later the binaries that it is incompatible with will have to
| be recompiled with a newer library if possible, or discarded if
| necessary. The sooner this happens, the better for everyone (except, of
| course, whoever it is that has to do the recompile or replace the
| discarded binary). As long as a backwards compatibility option is
| provided (it could even be the default, at least for the next decade or
| so), this shouldn't be a serious problem.

It does not need to be recompiled. The system just needs to keep a legacy
library for the old ABI, and use a new library for a new ABI (ABI's might
differ in just a few things like size of time_t and off_t).

Consider a function in one module which calls mktime() to get a time_t
value, which it then passes to a function in another module, which
passes that value to ctime(). The first module is compiled with the
headers for the old version of the library, and for one reason or
another it is not feasible or acceptable to recompile it with the
headers for the new library. The other module is compiled with the
headers for the new library. Since you've assured me that the first
module won't need to be recompiled, I can link those two modules
together to form a single program, without worrying about binary
compatibility problems, despite the change in both the size and
representation of time_t? I'm truly impressed - and also highly skeptical.
 
N

Nobody

FYI, the whole mess with 64 bit file offsets was done all wrong. It should
have simply been a new ABI that has a slightly different library name.
Keep both libraries where legacy binaries exist. All recompiles would by
default use the new ABI definitions.

There are other problems with file offsets, e.g. fseek/ftell using "long"
for the offset rather than off_t, passing file descriptors between
processes, etc.
 
O

Old Wolf

On 31 July, 07:49, Thomas Matthews


this isn't confined to Basic, I have a C++ application that faces the
same problem.

At least the C++ developers had the option of coding to
a standard, so that they could upgrade in future without
breaking. VB developers just have to hope that the
language proprietor doesn't break their code.
 
P

Phil Carmody

James Kuyper said:
Those which use time_t.

Except all the existing code I encounter uses a 64-bit time_t,
which has no binary incompatibility with the code that uses a
64-bit time_t. Are you having trouble with the English word
"precisely", as your attempt to generalised has yielded a 0%
hit rate from my persepective?

Phil
 
J

James Kuyper

Phil said:
Except all the existing code I encounter uses a 64-bit time_t,
which has no binary incompatibility with the code that uses a
64-bit time_t. Are you having trouble with the English word
"precisely", as your attempt to generalised has yielded a 0%
hit rate from my persepective?

Yes, I was having a great deal of trouble wondering what point you were
trying to make by asking for more precision than was justified by the
context of your request.

I didn't realize that you were addressing an issue other than the one
Richard Heathfield was talking about, namely whether or not backwards
compatibility is a legitimate reasons for delaying transition from
32-bit to 64-bit time_t. ABIs where that transition was made
sufficiently long ago that all binaries built for a 32-bit time_t have
disappeared, or which have never had to to make the transition because
they have always had 64-bit time_t, are irrelevant to that discussion.
The only ones where it matters are ones where binaries built for 32-bit
time_t still exist, and for one reason or another cannot be rebuilt for
for 64-bit time_t.

This isn't relevant for most of my work: my programs are all stored as
source code which I routinely recompile, often several times per day,
and link to libraries that are delivered as source code, not binaries,
so they could be recompiled too, if needed. However, I gather that
there's a fair number of people out there for whom backwards binary
compatibility is a big issue.
 
S

Stephen Sprunk

Good lord; would whoever that is please use the standard quote character
(i.e. '>') so we can figure out who said what?
I would assume, all of them, though I could be mistaken.

Do you know of any ABI where modules which communicate with each other
using time_t would remain binary compatible with each other if compiled
by compilers with different ideas of the size of time_t?

You can get pretty close with any ABI that specifies passing arguments
and return values in registers and where the underlying CPU will
sign-extend an undersized argument. Of course, that will stop working
when you need to represent times past Y2.038K (assuming the usual
32-vs-64-bit time_t problem), but that's an insolvable problem.

That won't work for the specific case of using a (time_t *), but I can't
recall having ever seen that in real code.

S
 
J

James Kuyper

Stephen said:
Good lord; would whoever that is please use the standard quote character
(i.e. '>') so we can figure out who said what?'

Talk with Phil about that.
You can get pretty close with any ABI that specifies passing arguments
and return values in registers and where the underlying CPU will
sign-extend an undersized argument. ...

An additional requirement is that the registers involved must be at
least 64 bit in size. That's true on many machines, but by no means all
of them.
... Of course, that will stop working
when you need to represent times past Y2.038K (assuming the usual
32-vs-64-bit time_t problem), but that's an insolvable problem.

Well, it's precisely that insolvable problem which is the point of this
discussion.
That won't work for the specific case of using a (time_t *), but I can't
recall having ever seen that in real code.

I can't think of any reason to rule it out as a possibility.
 
K

Kaz Kylheku

|> (e-mail address removed) writes:
|>>>
|>>> C does not mandate the use of 32-bit integers for time_t.
|>>> This is truly an implementation issue, and the fix is so easy that
|>>> implementors have no excuse for not fixing the problem right now.
|>>
|>> Binary compatibility with existing code seems like a pretty good excuse
|>> to me.
|>
|> Precisely which binary interfaces did you have in mind?
|
| One is the binary interface between a program and a dynamically linked
| C library, like say the time function.

C does not have binary interfaces.

Yes it does. Units of a C program can be separately translated, and
put together using linkage, which is a standard-defined concept. This linkage
depends on assumptions like that the units agree about the representation of
the types involved in that linkage.
 
N

Nobody

You can get pretty close with any ABI that specifies passing arguments
and return values in registers and where the underlying CPU will
sign-extend an undersized argument. Of course, that will stop working
when you need to represent times past Y2.038K (assuming the usual
32-vs-64-bit time_t problem), but that's an insolvable problem.

It also makes having a 64-bit time_t rather pointless. Either a 32-bit
time_t is a problem or it isn't. If it is a problem, then you need a
64-bit time_t *everywhere*.
That won't work for the specific case of using a (time_t *), but I can't
recall having ever seen that in real code.

It won't work for a structure field either.

The other problem with using a 64-bit time_t on a 32-bit system is code
which coerces a time_t to int or long. Most of the issues have already
been discovered in connection with using a 64-bit off_t on a 32-bit system.
 
D

Dik T. Winter

>
> At least the C++ developers had the option of coding to
> a standard, so that they could upgrade in future without
> breaking.

There have been a few incompatible C++ standards around.
 
S

Stephen Sprunk

James said:
An additional requirement is that the registers involved must be at
least 64 bit in size. That's true on many machines, but by no means all
of them.

Yes, I was assuming a 64-bit (i.e. 64-bit GPR) system. A 32-bit system
with a 64-bit time_t is going to be much more difficult to make
backwards-compatible, but such systems also seem to be rare in practice.
Well, it's precisely that insolvable problem which is the point of this
discussion.

I thought the problem being discussed was how to recompile libraries to
support a 64-bit time_t without breaking apps that use a 32-bit time_t.

Obviously those apps can never represent a time after Y2.038K; however,
an app that only needs to represent times in the past, present, or near
future would continue to work until near that time.

Without a transition plan, though, one could not compile _new_ apps for
the 64-bit time_t, which means those with _any_ legacy code they can't
recompile would be prevented from switching over -- and all _new_ code
would instantly become legacy code as well.
I can't think of any reason to rule it out as a possibility.

It's definitely possible, but if it isn't a problem in practice, i.e.
none of your legacy code actually uses it, it doesn't pose a backwards
compatibility problem with this strategy. New or recompiled code could
use a (time_t *) because the size of the time_t would match.

S
 
S

Stephen Sprunk

Please do not remove attribution lines. James Kuyper wrote the
following section, not me.
It also makes having a 64-bit time_t rather pointless. Either a 32-bit
time_t is a problem or it isn't. If it is a problem, then you need a
64-bit time_t *everywhere*.

_Existing_ code with a 32-bit time_t is going to eventually break;
nothing can be done about that. The problem is that, without being able
to transition to a 64-bit time_t, all _new_ code is also going to break,
and a transition is infeasible in some cases if the two cannot coexist.
It won't work for a structure field either.

I don't think a struct argument would be a problem; all of the ABIs I'm
familiar with pass a struct as if its members were individual arguments.

However, I now realize there _is_ a problem with passing a _pointer to_
a struct containing a time_t. I suspect that's common enough to rule
out this strategy, but I might be wrong.
The other problem with using a 64-bit time_t on a 32-bit system is code
which coerces a time_t to int or long. Most of the issues have already
been discovered in connection with using a 64-bit off_t on a 32-bit system.

Coercing a 64-bit time_t into a 32-bit int or long would hopefully cause
a compiler warning, regardless of the underlying ABI.

The problems _are_ similar to the transition of off_t from 32 to 64
bits. Hopefully we have learned from that and figure out a better
strategy; we also have a bit more time (no pun intended) to get it
right. The sudden growth of disks (and files) from a few megs to a few
gigs took a lot of folks by surprise, so it is no surprise that last-
minute kludges proliferated; we all know exactly when Y2.038K is coming.

On POSIX systems, the best technical solution is actually fairly simple:
up the library major version number and modify the headers at the same
time. Old apps will continue to be linked with the old libraries, and
new apps will be linked with the new libraries. Windows doesn't allow
multiple versions of a given DLL to coexist, though, which is the root
of the well-known "DLL Hell".

S
 
J

jameskuyper

Stephen said:
I thought the problem being discussed was how to recompile libraries to
support a 64-bit time_t without breaking apps that use a 32-bit time_t.

Yes, but only as step toward solving the bigger problem.
Obviously those apps can never represent a time after Y2.038K; however,
an app that only needs to represent times in the past, present, or near
future would continue to work until near that time.

What qualifies as "near that time" depends upon how far into the
future they use time_t. A 30-year mortgage schedule is already in
trouble. Other, shorter-term projections are going to start running
into trouble in the not-to-distant future.
It's definitely possible, but if it isn't a problem in practice, i.e.
none of your legacy code actually uses it, it doesn't pose a backwards
compatibility problem with this strategy. New or recompiled code could
use a (time_t *) because the size of the time_t would match.

Well, yes. Code that doesn't use time_t at all is also not in danger,
at least not directly.
 
J

jameskuyper

Richard said:
jameskuyper said:



I've worked on many financial services applications, and can attest to
the fact that time_t is /not/ normally used for projections. Yes,
it's used to find "today", so to speak, but then usually the dates
are rolled up "by hand". That's because it's actually easier that
way.

I would actually have expected that it's pretty common to use tools
other than C (like spreadsheets) and operating systems that are not
Unix-like (such as Windows) for such purposes, However, I'm not at all
clear on what you mean by 'rolled up "by hand"', and therefore am not
clear on why it would be easier that way.

Whatever the reason is, the point I was making is more general than
that specific example. Anyone using time_t to work with future times
is going to run into Y2038 problems ahead of "schedule", regardless of
how many people there are who are NOT using time_t for that purpose.
The farther ahead they're looking, the earlier they'll run into
problems; a 30 year mortgage was simply the longest-term ordinary
everyday application I could think of. Most of the applications I can
think of for long-term future time calculations were scientific, and
those can easily be dismissed as irrelevant to "ordinary people".
 
K

Kaz Kylheku

You can get pretty close with any ABI that specifies passing arguments
and return values in registers and where the underlying CPU will
sign-extend an undersized argument.
Of course, that will stop working
when you need to represent times past Y2.038K (assuming the usual
32-vs-64-bit time_t problem), but that's an insolvable problem.

That won't work for the specific case of using a (time_t *), but I can't
recall having ever seen that in real code.

Really? How about code which puts time_t into a struct and passes a pointer to
that struct?

How about external linkage: 32 bit ``extern time_t foo;'' ref, and
64 bit ``time_t foo;'' def?

Addresses in static storage have the same problems as pointers.
 
J

James Kuyper

Richard said:
jameskuyper said: ....

Well, Windows has time_t too! :)

Yes, but I thought that the Y2038 problem was specific to Unix-like
systems. I don't claim enough Windows expertise to be certain of that.
 

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,995
Messages
2,570,225
Members
46,815
Latest member
treekmostly22

Latest Threads

Top