473,503 Members | 1,720 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

getdelim: wrong specs

In the documents presented in the post Portland meeting
of the C standards comitee
http://www.open-std.org/jtc1/sc22/wg14/

there is a document called ISO/IEC WDTR 24731-2,
Specification for Safer C Library Functions —
Part II: Dynamic Allocation Functions

In that document we have:
ssize_t getdelim(char **restrict lineptr,
size_t *restrict n, int delimiter, FILE *stream);

We read:
< quote >

Upon successful completion the getdelim function shall return the number
of characters written into the buffer, including the delimiter character
if one was encountered before EOF. Otherwise it shall return −1.

< end quote >

We come back here to the error analysis problem, a problem that I
have been mentioning since ages and comes again and again. Returning
-1 to indicate "some error occurred but I will not tell you which"
is BAD DESIGN!

This function can have several errors that should be distinguished in
the return value of the function, i.e. there should be other return
values for signaling errors to the user. Lcc-win32 implements this
function and returns:

-5 No memory left for allocating the line
-4 Line pointer points to a buffer but n is <= 0. This is an error in
the incoming arguments.
-3 The n parameter is NULL
-2 The LinePointer parameter is NULL
-1 End of file without any characters read.

This is a much more detailed error reporting, that allows the
user of the function to discriminate between the different error
conditions. It is sad that a document that proposed "safer" functions
doesn't do the error analysis that is an essential part of safer
programming.
Dec 3 '06
61 4011
pete wrote:
I've never like the concept of EDOM.
That a programmer would write code to initialise errno
and check it after a function call, rather than to ensure
that the arguments were in the domain of the function,
seems strange to me.
Originally, EDOM was intended for math functions, where
an exact test for "within the domain" might be difficult
(consider atan), and also to catch accidents (programming
explicit validity tests before every usage is so tedious,
especially when one expects all usage to be valid, that
you can't rely on users to do it). It would have been
much better to have used a generic nested-exception
handling facility, which allows fine-grained override of
global error-handling strategy. A sort of in-between
approach showed up in the commercial branch of Unix, in
the form of a function named "matherror" for which the
user could substitute his own version.
Dec 11 '06 #51
Richard Heathfield said:
Harald van D?k said:
<snip>
>
>but if you don't mind unspecified output,
this works in Borland C++ 5.5 (in C mode):

No time right now - I'll check it as soon as I get home. (After getting my
coat off, making some coffee, ... but you get the idea.)
<sighBetter late than never. Anyway, I've just checked your code in BC5.6
and it works fine. So either they finally fixed this, or I was imagining
things. Which do you reckon? (Don't answer that...)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 12 '06 #52

Douglas A. Gwyn wrote:
>
Originally, EDOM was intended for math functions, where
an exact test for "within the domain" might be difficult
(consider atan),
Reasonable.
and also to catch accidents (programming
explicit validity tests before every usage is so tedious,
especially when one expects all usage to be valid, that
you can't rely on users to do it).
I doubt that justifies existence of EDOM; that's what we're doing in
C everyday.
--
Jun, Woong (woong at icu.ac.kr)
Samsung Electronics Co., Ltd.

``All opinions expressed are mine, and do not represent
the official opinions of any organization.''

Dec 12 '06 #53
CBFalconer <cb********@yahoo.comwrote:
Richard Bos wrote:
jacob navia <ja***@jacob.remcomp.frwrote:
Why is a result value a bad design? Can you explain?
_A_ result value is not. Using random negative values for errors
and positive values for non-errors is fragile. It presumes that
correct results will never overflow into negative values, for
example. _If_ you know that this will never happen, that's fine,
but this function is meant as an enhancement to the Standard, not
as part of a single program with predictable input, so it needs
to be more solid than most.

For the record: I have nothing against your solution _for a user
function_. For a (meant to become Standard) library function,
though, I strongly suggest using the Standard mechanism for
reporting errors.

Take a look at the error reporting in ggets. It is controlled by
an enum for positive values, and EOF for negative values. No
possibility of overflow (which in itself would be undefined
behaviour) exist.
That's arguably better design, but it's not the design that was used in
the proposed getdelim() specification in the first place. Using EOF as
an in-band error value for that was less than ideal; using -1 through
-5, disregarding possible other values of EOF than -1, is worse.

Richard
Dec 12 '06 #54
Richard Bos a écrit :
>
That's arguably better design, but it's not the design that was used in
the proposed getdelim() specification in the first place. Using EOF as
an in-band error value for that was less than ideal; using -1 through
-5, disregarding possible other values of EOF than -1, is worse.

Richard
No it is not. The result value is a ssize_t, i.e. a signed size_t.
This means that all negative values are free to use as error
values since the valid return values are from zero to INT_MAX.

ssize_t getdelim(char **restrict lineptr,
size_t *restrict n,
int delimiter, FILE *stream);
Dec 12 '06 #55
jacob navia wrote:
Richard Bos a écrit :
>>
That's arguably better design, but it's not the design that was
used in+ the proposed getdelim() specification in the first place.
Using EOF as an in-band error value for that was less than ideal;
using -1 through -5, disregarding possible other values of EOF
than -1, is worse.

No it is not. The result value is a ssize_t, i.e. a signed size_t.
This means that all negative values are free to use as error
values since the valid return values are from zero to INT_MAX.

ssize_t getdelim(char **restrict lineptr,
size_t *restrict n,
int delimiter, FILE *stream);
There is no guarantee as to the value of EOF, other than that it is
negative. Any mapping into a size_t runs the risk of clashes. Use
an int to return EOF.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Dec 12 '06 #56
CBFalconer <cb********@yahoo.comwrites:
jacob navia wrote:
>Richard Bos a écrit :
>>>
That's arguably better design, but it's not the design that was
used in+ the proposed getdelim() specification in the first place.
Using EOF as an in-band error value for that was less than ideal;
using -1 through -5, disregarding possible other values of EOF
than -1, is worse.

No it is not. The result value is a ssize_t, i.e. a signed size_t.
This means that all negative values are free to use as error
values since the valid return values are from zero to INT_MAX.

ssize_t getdelim(char **restrict lineptr,
size_t *restrict n,
int delimiter, FILE *stream);

There is no guarantee as to the value of EOF, other than that it is
negative. Any mapping into a size_t runs the risk of clashes. Use
an int to return EOF.
You could declare an enumerated type whose constants specify the
various error conditions. The values of the constants wouldn't have
to be consistent from one implementation to another, just their names.
It would be up to the implementer to avoid colliding with the value of
EOF. (EOF is -1 on every implementation I've ever heard of; a
programmer can't safely make that assumption, but an implementer can.)

For example:

enum {
ERROR_MAX = -2,
ERROR_FOO = -2,
ERROR_BAR = -3,
ERROR_BAZ = -4,
ERROR_XYZ = -5,
ERROR_MIN = -5
};

There's no tag for the enumerated type because it's used only to
declare a series of constants.

getdelim() could still return ssize_t (I've lost track, are we
assuming that ssize_t exists?), and it could be used like this:

ssize_t result = getdelim(arg1, arg2, arg3, arg4);
if (result >= 0) {
/* ... */
}
else if (result == EOF) {
/* ... */
}
else if (result >= ERROR_MIN && result <= ERROR_MAX) {
switch(result) {
case ERROR_FOO: /* ... */
/* ... */
default: /* ... */
}
}

This lets you squeeze valid results, EOF, and multiple error codes
into a single return value. It also assumes that losing half the
range of size_t isn't a problem.

I'm not claiming that this is a particularly good approach, just that
it's possible.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 12 '06 #57
Keith Thompson <ks***@mib.orgwrites:
You could declare an enumerated type whose constants specify the
various error conditions. The values of the constants wouldn't have
to be consistent from one implementation to another, just their names.
It would be up to the implementer to avoid colliding with the value of
EOF. (EOF is -1 on every implementation I've ever heard of; a
programmer can't safely make that assumption, but an implementer can.)
I think that this kind of dodge would consistently avoid EOF and
positive values:

enum {
MY_ERR_MIN = EOF ^ 0x100,

MY_ERR_FIRSTERR = MY_ERR_MIN,
MY_ERR_SECONDERR,
MY_ERR_ANOTHERERR,
...etc...

MY_ERR_SENTINEL,
MY_ERR_MAX = MY_ERR_SENTINEL - 1
};
--
Ben Pfaff
email: bl*@cs.stanford.edu
web: http://benpfaff.org
Dec 12 '06 #58
Keith Thompson wrote:
CBFalconer <cb********@yahoo.comwrites:
>>jacob navia wrote:
>>>Richard Bos a écrit :

That's arguably better design, but it's not the design that was
used in+ the proposed getdelim() specification in the first place.
Using EOF as an in-band error value for that was less than ideal;
using -1 through -5, disregarding possible other values of EOF
than -1, is worse.

No it is not. The result value is a ssize_t, i.e. a signed size_t.
This means that all negative values are free to use as error
values since the valid return values are from zero to INT_MAX.

ssize_t getdelim(char **restrict lineptr,
size_t *restrict n,
int delimiter, FILE *stream);

There is no guarantee as to the value of EOF, other than that it is
negative. Any mapping into a size_t runs the risk of clashes. Use
an int to return EOF.


You could declare an enumerated type whose constants specify the
various error conditions. The values of the constants wouldn't have
to be consistent from one implementation to another, just their names.
It would be up to the implementer to avoid colliding with the value of
EOF. (EOF is -1 on every implementation I've ever heard of; a
programmer can't safely make that assumption, but an implementer can.)

For example:

enum {
ERROR_MAX = -2,
ERROR_FOO = -2,
ERROR_BAR = -3,
ERROR_BAZ = -4,
ERROR_XYZ = -5,
ERROR_MIN = -5
};

There's no tag for the enumerated type because it's used only to
declare a series of constants.

getdelim() could still return ssize_t (I've lost track, are we
assuming that ssize_t exists?), and it could be used like this:

ssize_t result = getdelim(arg1, arg2, arg3, arg4);
if (result >= 0) {
/* ... */
}
else if (result == EOF) {
/* ... */
}
else if (result >= ERROR_MIN && result <= ERROR_MAX) {
switch(result) {
case ERROR_FOO: /* ... */
/* ... */
default: /* ... */
}
}

This lets you squeeze valid results, EOF, and multiple error codes
into a single return value. It also assumes that losing half the
range of size_t isn't a problem.

I'm not claiming that this is a particularly good approach, just that
it's possible.

This looks VERY reasonable. Thanks

jacob
Dec 12 '06 #59
jacob navia <ja***@jacob.remcomp.frwrites:
Keith Thompson wrote:
[...]
>It would be up to the implementer to avoid colliding with the value of
EOF. (EOF is -1 on every implementation I've ever heard of; a
programmer can't safely make that assumption, but an implementer can.)
For example:
[big snip]
This looks VERY reasonable. Thanks

jacob
Um, I have mixed feelings about that. I was trying to create the most
reasonable design given the assumption that you want to squeeze valid
results, EOF, and multiple error conditions into a single return
value. Personally, I don't particularly like the assumption.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 12 '06 #60
Ben Pfaff wrote:
I think that this kind of dodge would consistently avoid EOF and
positive values:

enum {
MY_ERR_MIN = EOF ^ 0x100,

MY_ERR_FIRSTERR = MY_ERR_MIN,
MY_ERR_SECONDERR,
MY_ERR_ANOTHERERR,
...etc...

MY_ERR_SENTINEL,
MY_ERR_MAX = MY_ERR_SENTINEL - 1
};
Not if EOF is 0x100. There's also the risk that you might end up with
more than 256 error messages...
--
ais523

Dec 13 '06 #61

ais523 wrote:
Ben Pfaff wrote:
I think that this kind of dodge would consistently avoid EOF and
positive values:

enum {
MY_ERR_MIN = EOF ^ 0x100,

MY_ERR_FIRSTERR = MY_ERR_MIN,
MY_ERR_SECONDERR,
MY_ERR_ANOTHERERR,
...etc...

MY_ERR_SENTINEL,
MY_ERR_MAX = MY_ERR_SENTINEL - 1
};
Not if EOF is 0x100. There's also the risk that you might end up with
-0x100, obviously.
more than 256 error messages...
--
ais523

Dec 13 '06 #62

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

43
3366
by: Mr.Tickle | last post by:
// Run this code and look for his obvious error by the compiler namespace FlagCheck { using System; enum SomeFlags {
23
3094
by: rithish | last post by:
<code> var dt = new Date(2004, 0, 1); alert ( dt.getDate() ); // returns proper date alert ( dt.getUTCFullYear() ); // returns 2003 </code> Why is this so? Or is that I am missing...
10
2041
by: G Matthew J | last post by:
interesting "signal vs. noise" blog entry: http://37signals.com/svn/archives2/whats_wrong_with_ajax.php
2
3662
by: Alok | last post by:
Hi, I recently upsized my access database to an ADP project with SQL backend. However when I did it the import/export specs were not ported to the new database. Also in the ADP files I am unable...
1
1074
by: Michael B Allen | last post by:
Is there anything wrong with this macro? #define randint(a,b) (a)+(((b)-(a)+1)*(float)rand()/RAND_MAX) If I do randint(10, 0x10000) in a loop it sporatically generates: Program received...
3
3266
by: snowweb | last post by:
I'm creating my first web application in PHP/MySQL, however, when I go to view the database contents, the data has been stored in the wrong columns. I've gone through my insertion code with a fine...
2
1911
by: safak112 | last post by:
Hi everybody; I am exporting a table to a new txt file by using MS access 2000. But as you know we can save our export specs, and next time we can call it and can use it once more. But in my...
10
1256
by: Mantorok | last post by:
What are realistic PC specs for using Visual Studio 2005? Thanks Kev
0
1473
by: Grant Edwards | last post by:
I've got a system where I try to install extensions using /usr/local/bin/python setup.py install But, it fails when it tries to use a non-existant compiler path and specs file. I suspect it's...
0
7192
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7064
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7261
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
6974
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
4665
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3158
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3147
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
721
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
369
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.