473,385 Members | 1,396 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

malloc()/realloc() - have I got this right?

Hello,

I'm teaching myself C by working my way through Steve Summit's tutorial
(http://www.eskimo.com/~scs/cclass/cclass.html). In one of the questions
(assignment 6, exercise 7), you have to write a function to read lines of
arbitrary length from the command line, using malloc() and realloc() to
allocate the necessary memory to hold the lines. I came up with this:

char *getline(char *line)
{
int line_len = 0;
int max_len = 32; /* initial guess */
char *start; /* pointer to start of string is the return value */
char *count;
int c;

line = malloc(max_len * sizeof(char));
if (line == NULL)
{
printf("Out of memory.\n");
exit(1);
}
start = line;
count = line;

while ((c = getchar()) != EOF)
{
if (c == '\n')
break;
if (line_len == max_len - 1)
{
max_len *= 2;
line = realloc(line, max_len * sizeof(char));
if (line == NULL)
{
printf("Out of memory.\n");
exit(1);
}
}

*count++ = c;
line_len++;
}
*count = '\0';
return start;
}

And I'm using this to test it:

int main()
{
char *line;
int i;
for (i = 0; i < 5; i++)
{
line = getline(line);
printf("%s\n%d\n", line, strlen(line));
}
return 0;
}

On Linux it seems to work with lines of any length. On Windows (using the
MinGW compiler) it fails if the line is longer than 1024 characters (just
prints out a few random characters and reports the length as 0). I'm
hoping someone can tell me if I've got this function basically right -
have I introduced some bug which is causing the crash, or is it a Windows
thing that I don't need to concern myself with?

Also, is it better in principle to make more calls to realloc() to ensure
that you get exactly the memory you need and no more, or to make fewer
calls and just malloc() more than you think you'll need at the beginning?

Thanks for any help.
Jun 27 '08 #1
40 1941
In article <Hs******************************@pipex.net>,
Dave <da**@mailinator.comwrote:
>I'm teaching myself C by working my way through Steve Summit's tutorial
(http://www.eskimo.com/~scs/cclass/cclass.html). In one of the questions
(assignment 6, exercise 7), you have to write a function to read lines of
arbitrary length from the command line
Cutting the code down the essentials:
>char *getline(char *line)
{
char *start; /* pointer to start of string is the return value */
char *count;
line = malloc(max_len * sizeof(char));
start = line;
count = line;
while ((c = getchar()) != EOF)
{
if (line_len == max_len - 1)
{
max_len *= 2;
line = realloc(line, max_len * sizeof(char));
}
*count++ = c;
}
return start;
}
You have a logical bug there. If realloc has to move line,
then because start and count point into the same space as
the original line, count and start become logically invalidated.

I believe if you look at your code again, you will see that start
is not of any value in the code (you can return line instead of start),
and that count would perhaps make more sense as a size_t used
as an index into the line array:

line[count++] = c;
--
"The art of storytelling is reaching its end because the epic
side of truth, wisdom, is dying out." -- Walter Benjamin
Jun 27 '08 #2
Dave <da**@mailinator.comwrote:
I'm teaching myself C by working my way through Steve Summit's tutorial
(http://www.eskimo.com/~scs/cclass/cclass.html). In one of the questions
(assignment 6, exercise 7), you have to write a function to read lines of
arbitrary length from the command line, using malloc() and realloc() to
allocate the necessary memory to hold the lines. I came up with this:
It would be better if you also would show which header files
you're including, it's not uncommon that a few essential ones
get forgotten...
char *getline(char *line)
Why do you pass 'line' to the function if you don't use its
value anywhere?
{
int line_len = 0;
int max_len = 32; /* initial guess */
char *start; /* pointer to start of string is the return value */
char *count;
I would recommend to rename that to something more fitting
like 'current_pointer' or 'next' or maybe 'end' something
like that. It helps in the long run to have variable names
that quickly tell you what they are used for. And 'count'
sounds a lot like a counter variable, not a pointer.
int c;
line = malloc(max_len * sizeof(char));
You could drop the 'sizeof(char)' since it's guaranteed to
be 1. Or replace it by 'sizeof *line'.
if (line == NULL)
{
printf("Out of memory.\n");
exit(1);
}
start = line;
count = line;
while ((c = getchar()) != EOF)
{
if (c == '\n')
break;
if (line_len == max_len - 1)
{
max_len *= 2;
line = realloc(line, max_len * sizeof(char));
if (line == NULL)
{
printf("Out of memory.\n");
exit(1);
}
What you're not taking into account here is that realloc()
could set 'line' to a new value. If that happens you also
have to readjust 'count' by I guess

count = line + line_len;
}
*count++ = c;
line_len++;
}
*count = '\0';
return start;
And here is another potential problem lurking. If 'line' got
changed to a new value during one of the realloc() calls you
will return a pointer to some memory that you don't own any-
more. You can drop the 'start' variable completely and in-
stead simply return 'line'.

Another thing you could do before returning (if you don't want
to waste any memory) is to realloc() 'line' to the exact length
you needed for the string.
}
And I'm using this to test it:
int main()
{
char *line;
int i;
for (i = 0; i < 5; i++)
{
line = getline(line);
printf("%s\n%d\n", line, strlen(line));
If I switch to very picky mode I would point out that strlen()
returns a size_t value, so using "%d" to print it is not
strictly correct. I would probably use

printf("%s\n%lu\n", line, (unsigned long) strlen(line));

(unless you have a C999 compiler where you have a format
specifier for size_t).
}
return 0;
}
On Linux it seems to work with lines of any length. On Windows (using the
MinGW compiler) it fails if the line is longer than 1024 characters (just
prints out a few random characters and reports the length as 0). I'm
hoping someone can tell me if I've got this function basically right -
have I introduced some bug which is causing the crash, or is it a Windows
thing that I don't need to concern myself with?
I can only guess but it might be related to the problem that you
don't consider that realloc() might return a different pointer
for the memory.
Also, is it better in principle to make more calls to realloc() to ensure
that you get exactly the memory you need and no more, or to make fewer
calls and just malloc() more than you think you'll need at the beginning?
You can always reduce the memory by using realloc() in the end.
malloc() and realloc() can be rather expensive functions, so if
you really have to worry about execution speed you may get some
speed-up if you try to reduce the number of calls of these func-
tions. But that's something you should measure, not just assume.

Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Jun 27 '08 #3
Dave wrote, On 27/05/08 23:56:
Hello,

I'm teaching myself C by working my way through Steve Summit's tutorial
(http://www.eskimo.com/~scs/cclass/cclass.html). In one of the questions
(assignment 6, exercise 7), you have to write a function to read lines of
arbitrary length from the command line, using malloc() and realloc() to
allocate the necessary memory to hold the lines. I came up with this:

char *getline(char *line)
Why are you passing in line as a parameter? You only go and overwrite
its value a few lines further down.
{
int line_len = 0;
int max_len = 32; /* initial guess */
char *start; /* pointer to start of string is the return value */
char *count;
int c;

line = malloc(max_len * sizeof(char));
sizeof(char) is one by definition so there is no point multiplying by it.
if (line == NULL)
{
printf("Out of memory.\n");
exit(1);
1 is not a portable value for exit. If you are just flagging failure use
EXIT_FAILURE from stdlib.h
}
start = line;
count = line;

while ((c = getchar()) != EOF)
{
if (c == '\n')
break;
if (line_len == max_len - 1)
{
max_len *= 2;
line = realloc(line, max_len * sizeof(char));
What value will start have after this line? In particular, what happens
if realloc actually moves the block?
if (line == NULL)
{
printf("Out of memory.\n");
exit(1);
}
}

*count++ = c;
line_len++;
}
*count = '\0';
return start;
}

And I'm using this to test it:

int main()
{
char *line;
int i;
for (i = 0; i < 5; i++)
{
line = getline(line);
First time round line is uninitialised when passed in, you get away with
it by luck, but it is still undefined behaviour (i.e. *anything* can
happen, including the program "working" or all the molecules in your
undergarments simultaneously jumping one foot to the left).

On the second time round you leak the memory that line used to point to.
printf("%s\n%d\n", line, strlen(line));
strlen returns a size_t, %d expects an int. For C89 cast the value to
unsigned long and use the appropriate format specifier (this is one of
the few occasions where a cast is useful).
}
return 0;
}

On Linux it seems to work with lines of any length. On Windows (using the
MinGW compiler) it fails if the line is longer than 1024 characters (just
prints out a few random characters and reports the length as 0). I'm
hoping someone can tell me if I've got this function basically right -
have I introduced some bug which is causing the crash, or is it a Windows
thing that I don't need to concern myself with?
On something like this it is almost always going to be your code at
fault. In this case I am 99% sure it is one of the problems I've pointed
out above and I even know which one, but you should now be able to work
out which bug it is for yourself and then fix *all* of the bugs.
Also, is it better in principle to make more calls to realloc() to ensure
that you get exactly the memory you need and no more, or to make fewer
calls and just malloc() more than you think you'll need at the beginning?
That all depends on what the likely input is. If the input is most
likely to be typed then starting with a fixed line size and increasing
by either a small multiplier (a lot less than 2) or a linear increase
makes more sense than doubling.
--
Flash Gordon
Jun 27 '08 #4
Dave wrote:
>
I'm teaching myself C by working my way through Steve Summit's
tutorial (http://www.eskimo.com/~scs/cclass/cclass.html). In one
of the questions (assignment 6, exercise 7), you have to write a
function to read lines of arbitrary length from the command line,
using malloc() and realloc() to allocate the necessary memory to
hold the lines. I came up with this:
Instead of all that just get ggets.zip from:

<http://cbfalconer.home.att.net/download/ggets.zip>

and read ggets.c (less code that yours, all standard). Then decide
if you want to use it (I have put it in the public domain) or adapt
it to your purposes.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

** Posted from http://www.teranews.com **
Jun 27 '08 #5
CBFalconer said:
Dave wrote:
>>
I'm teaching myself C by working my way through Steve Summit's
tutorial (http://www.eskimo.com/~scs/cclass/cclass.html). In one
of the questions (assignment 6, exercise 7), you have to write a
function to read lines of arbitrary length from the command line,
using malloc() and realloc() to allocate the necessary memory to
hold the lines. I came up with this:

Instead of all that just get ggets.zip from:

<http://cbfalconer.home.att.net/download/ggets.zip>
Be aware, if you do so, that the above routine has what some people
consider to be serious design flaws. And of course you'll learn more by
writing your own than you will by pinching someone else's.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 27 '08 #6
CBFalconer <cb********@yahoo.comwrites:
Dave wrote:
>I'm teaching myself C by working my way through Steve Summit's
tutorial (http://www.eskimo.com/~scs/cclass/cclass.html). In one
of the questions (assignment 6, exercise 7), you have to write a
function to read lines of arbitrary length from the command line,
using malloc() and realloc() to allocate the necessary memory to
hold the lines. I came up with this:

Instead of all that just get ggets.zip from:

<http://cbfalconer.home.att.net/download/ggets.zip>

and read ggets.c (less code that yours, all standard). Then decide
if you want to use it (I have put it in the public domain) or adapt
it to your purposes.
Which would not serve the purpose of teaching himself C nearly as well
as implementing his own. Reading code and writing code are both
valuable skills, but they're not interchangeable.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #7
Richard Heathfield wrote:
CBFalconer said:
>Dave wrote:
>>>
I'm teaching myself C by working my way through Steve Summit's
tutorial (http://www.eskimo.com/~scs/cclass/cclass.html). In one
of the questions (assignment 6, exercise 7), you have to write a
function to read lines of arbitrary length from the command line,
using malloc() and realloc() to allocate the necessary memory to
hold the lines. I came up with this:

Instead of all that just get ggets.zip from:

<http://cbfalconer.home.att.net/download/ggets.zip>

Be aware, if you do so, that the above routine has what some people
consider to be serious design flaws. And of course you'll learn
more by writing your own than you will by pinching someone else's.
Here, without the documentation, .h file, test routines, etc. is
the actual (standard C) code for ggets.c. Instead of listening to
the mewling of people who don't like to see malloc called within a
routine, read the code, and make your own decision. ggets is a
macro in ggets.h that uses the FILE stdin.

#include <stdio.h>
#include <stdlib.h>
#include "ggets.h"

#define INITSIZE 112 /* power of 2 minus 16, helps malloc */
#define DELTASIZE (INITSIZE + 16)

enum {OK = 0, NOMEM};

int fggets(char* *ln, FILE *f)
{
int cursize, ch, ix;
char *buffer, *temp;

*ln = NULL; /* default */
if (NULL == (buffer = malloc(INITSIZE))) return NOMEM;
cursize = INITSIZE;

ix = 0;
while ((EOF != (ch = getc(f))) && ('\n' != ch)) {
if (ix >= (cursize - 1)) { /* extend buffer */
cursize += DELTASIZE;
if (NULL == (temp = realloc(buffer, (size_t)cursize))) {
/* ran out of memory, return partial line */
buffer[ix] = '\0';
*ln = buffer;
return NOMEM;
}
buffer = temp;
}
buffer[ix++] = ch;
}
if ((EOF == ch) && (0 == ix)) {
free(buffer);
return EOF;
}

buffer[ix] = '\0';
if (NULL == (temp = realloc(buffer, (size_t)ix + 1))) {
*ln = buffer; /* without reducing it */
}
else *ln = temp;
return OK;
} /* fggets */
/* End of ggets.c */

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #8
CBFalconer said:

<snip>
Here, without the documentation, .h file, test routines, etc. is
the actual (standard C) code for ggets.c. Instead of listening to
the mewling of people who don't like to see malloc called within a
routine,
....of whom I am not one...
read the code, and make your own decision.
Okay.
ggets is a macro in ggets.h that uses the FILE stdin.
Fair enough, although presumably you mean FILE *.
>
#include <stdio.h>
#include <stdlib.h>
#include "ggets.h"

#define INITSIZE 112 /* power of 2 minus 16, helps malloc */
MIGHT help malloc. It depends on the implementation.
#define DELTASIZE (INITSIZE + 16)

enum {OK = 0, NOMEM};
Are those the only two failure conditions? What about end of file? Or a
stream error? Why not make it possible to report those?
int fggets(char* *ln, FILE *f)
{
int cursize, ch, ix;
char *buffer, *temp;

*ln = NULL; /* default */
The problem with this approach, as I have explained before, is that it
doesn't allow the caller to re-use an existing buffer. If they try, the
above line leaks the previous memory!
if (NULL == (buffer = malloc(INITSIZE))) return NOMEM;
cursize = INITSIZE;

ix = 0;
while ((EOF != (ch = getc(f))) && ('\n' != ch)) {
if (ix >= (cursize - 1)) { /* extend buffer */
cursize += DELTASIZE;
The problem with this approach is that it doesn't scale well. Remember that
stdin doesn't necessarily mean keyboard input. The input might, for
example, be coming from a very, very fast fixed disk. Consider changing to
an exponential approach, e.g. cursize *= 2; (or even cursize *= 1.1 or
something like that, which is fine if cursize starts with a value of at
least 10, which it does in this case).
if (NULL == (temp = realloc(buffer, (size_t)cursize))) {
The problem with this approach is that it runs a significant risk of
exhausting memory without the programmer having any control over this.
Consider accepting a parameter that specifies the largest buffer size this
call is allowed to allocate.

<snip>

These are genuine concerns. Your continued failure to address them is, of
course, entirely your decision, but I am at a loss to understand how you
can possibly recommend such a function (which you do, continually) whilst
these flaws remain.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 27 '08 #9
Richard Heathfield wrote:
CBFalconer said:
.... snip ...
>>
enum {OK = 0, NOMEM};

Are those the only two failure conditions? What about end of file?
Or a stream error? Why not make it possible to report those?
You didn't read the whole routine. It also returns EOF, which is
not defined here. I did point out that this listing omitted the
documentation etc.
>
The problem with this approach, as I have explained before, is
that it doesn't allow the caller to re-use an existing buffer.
If they try, the above line leaks the previous memory!
In your opinion. Similarly, never use malloc to set a pre-existing
pointer variable. Buffer reuse would require additional
parameters, and user confusion. Avoided.
>>
ix = 0;
while ((EOF != (ch = getc(f))) && ('\n' != ch)) {
if (ix >= (cursize - 1)) { /* extend buffer */
cursize += DELTASIZE;

The problem with this approach is that it doesn't scale well.
Remember that stdin doesn't necessarily mean keyboard input. The
input might, for example, be coming from a very, very fast fixed
disk. Consider changing to an exponential approach, e.g. cursize
*= 2; (or even cursize *= 1.1 or something like that, which is
fineat if cursize starts with a value of least 10, which it does
in this case).
Which it is not intended to. It will work for any size, but is
optimized for those sizes expected as interactive input. Note that
the user can alter this part of the algorithm easily.
>
> if (NULL == (temp = realloc(buffer, (size_t)cursize))) {

The problem with this approach is that it runs a significant risk
of exhausting memory without the programmer having any control over
this. Consider accepting a parameter that specifies the largest
buffer size this call is allowed to allocate.
The point is to avoid the need for any extra parameters and
associated confusion.
>
These are genuine concerns. Your continued failure to address them
is, of course, entirely your decision, but I am at a loss to
understand how you can possibly recommend such a function (which you
do, continually) whilst these flaws remain.
Yes, similarly it is a great evil to have file open functions,
since failure to close them may cause data loss. You are confusing
faults with design objectives. All these points have been answered
before, and you are perfectly free not to use ggets.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #10
CBFalconer said:
Richard Heathfield wrote:
>CBFalconer said:
... snip ...
>>>
enum {OK = 0, NOMEM};

Are those the only two failure conditions? What about end of file?
Or a stream error? Why not make it possible to report those?

You didn't read the whole routine. It also returns EOF, which is
not defined here. I did point out that this listing omitted the
documentation etc.
Your point is well-taken, although it does seem that you fail to
distinguish between genuine end-of-file and a stream error.
>The problem with this approach, as I have explained before, is
that it doesn't allow the caller to re-use an existing buffer.
If they try, the above line leaks the previous memory!

In your opinion.
It is true that the claim that it is a problem is a matter of opinion. It
is not a matter of opinion, however, that an attempt to re-use an existing
buffer *will* leak memory.
Similarly, never use malloc to set a pre-existing
pointer variable. Buffer reuse would require additional
parameters, and user confusion. Avoided.
Yes, it would require additional parameters. User confusion can stem from
many sources, though: for example, "why is my program leaking like a
sieve?" or (for those who've worked this out, perhaps by reading the docs)
"why can't I re-use this perfectly good buffer?"
>> ix = 0;
while ((EOF != (ch = getc(f))) && ('\n' != ch)) {
if (ix >= (cursize - 1)) { /* extend buffer */
cursize += DELTASIZE;

The problem with this approach is that it doesn't scale well.
Remember that stdin doesn't necessarily mean keyboard input. The
input might, for example, be coming from a very, very fast fixed
disk. Consider changing to an exponential approach, e.g. cursize
*= 2; (or even cursize *= 1.1 or something like that, which is
fineat if cursize starts with a value of least 10, which it does
in this case).

Which it is not intended to.
I'm puzzled. Do you mean that it's not intended to scale well?
It will work for any size,
This suggests that it /is/ expected to scale well, which it fails to do.
but is
optimized for those sizes expected as interactive input.
I disagree. If input is interactive and therefore relatively thin, asking
for a multiple of the existing memory isn't going to cause a delay any
more noticeable than that suffered when asking for a fixed additional
amount. So in fact it's not (usefully) optimised for interactive input.
Rather, it's pessimised for non-interactive input.
Note that
the user can alter this part of the algorithm easily.
If by "user" you mean "programmer", yes, a reasonably skilled programmer
can do that quite easily. But why should he or she have to, when it's so
easy for the problem to be fixed at source?
>> if (NULL == (temp = realloc(buffer, (size_t)cursize))) {

The problem with this approach is that it runs a significant risk
of exhausting memory without the programmer having any control over
this. Consider accepting a parameter that specifies the largest
buffer size this call is allowed to allocate.

The point is to avoid the need for any extra parameters and
associated confusion.
I think you under-estimate the ability of computer programmers to deal with
what is, after all, a pretty simple interface even /with/ the extra
parameters.
>These are genuine concerns. Your continued failure to address them
is, of course, entirely your decision, but I am at a loss to
understand how you can possibly recommend such a function (which you
do, continually) whilst these flaws remain.

Yes, similarly it is a great evil to have file open functions,
since failure to close them may cause data loss.
No, but it would be silly to have a function that, if passed a stream
pointer, immediately closes it just so that it can have the fun of opening
it again.
You are confusing faults with design objectives.
No, I'm saying that the design objective is flawed. For a very slight
change in the design, you can make the function considerably more useful,
but you choose not to do that.
All these points have been answered before,
To say, in effect, "tisn't" is not what I consider a sensible answer.
and you are perfectly free not to use ggets.
It is a freedom that I guard jealously, and I commend the same approach to
others until ggets is fixed to deal with the problems I've raised.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 27 '08 #11
Richard Heathfield <rj*@see.sig.invalidwrites:
CBFalconer said:
>Richard Heathfield wrote:
>>CBFalconer said:
... snip ...
>>>>
enum {OK = 0, NOMEM};

Are those the only two failure conditions? What about end of file?
Or a stream error? Why not make it possible to report those?

You didn't read the whole routine. It also returns EOF, which is
not defined here. I did point out that this listing omitted the
documentation etc.

Your point is well-taken, although it does seem that you fail to
distinguish between genuine end-of-file and a stream error.
So does fgets(). That's what feof() and ferror() are for.

[snip]

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #12
Keith Thompson said:
Richard Heathfield <rj*@see.sig.invalidwrites:
<snip>
>Your point is well-taken, although it does seem that you fail to
distinguish between genuine end-of-file and a stream error.

So does fgets().
Yes, which is another of its faults.
That's what feof() and ferror() are for.
A recoverable fault, therefore, but still a fault.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 27 '08 #13
Keith Thompson wrote:
Richard Heathfield <rj*@see.sig.invalidwrites:
>CBFalconer said:
>>Richard Heathfield wrote:
CBFalconer said:

... snip ...
>
enum {OK = 0, NOMEM};

Are those the only two failure conditions? What about end of file?
Or a stream error? Why not make it possible to report those?

You didn't read the whole routine. It also returns EOF, which is
not defined here. I did point out that this listing omitted the
documentation etc.

Your point is well-taken, although it does seem that you fail to
distinguish between genuine end-of-file and a stream error.

So does fgets(). That's what feof() and ferror() are for.

[snip]
Nothing can be done about fgets but a new function /could/ disambiguate
between these two conditions thus freeing the caller from some more
repetitive work.

Jun 27 '08 #14
Richard Heathfield <rj*@see.sig.invalidwrites:
Keith Thompson said:
>Richard Heathfield <rj*@see.sig.invalidwrites:

<snip>
>>Your point is well-taken, although it does seem that you fail to
distinguish between genuine end-of-file and a stream error.

So does fgets().

Yes, which is another of its faults.
>That's what feof() and ferror() are for.

A recoverable fault, therefore, but still a fault.
Point taken.

On the other hand, fgets()'s failure to distinguish between
end-of-file and an error isn't all *that* bad, and there's some virtue
in sticking to the model used by the standard library.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #15
Keith Thompson wrote, On 30/05/08 20:00:
Richard Heathfield <rj*@see.sig.invalidwrites:
>Keith Thompson said:
>>Richard Heathfield <rj*@see.sig.invalidwrites:
<snip>
>>>Your point is well-taken, although it does seem that you fail to
distinguish between genuine end-of-file and a stream error.
So does fgets().
Yes, which is another of its faults.
>>That's what feof() and ferror() are for.
A recoverable fault, therefore, but still a fault.

Point taken.

On the other hand, fgets()'s failure to distinguish between
end-of-file and an error isn't all *that* bad, and there's some virtue
in sticking to the model used by the standard library.
I don't think using two different negative values to distinguish between
error and end-of-file would be too much of a variation since some
functions which return an int like CBFs ggets (e.g. getc) use EOF for
failure (guaranteed to be negative) and non-negative values for success.
Of course, selecting the two negative values is a bit of a pain, but...

#if EOF==-1
#define FERROR (EOF-1)
#else
#define FERROR (EOF+1)
#endif
--
Flash Gordon
Jun 27 '08 #16
santosh wrote:
Keith Thompson wrote:
>Richard Heathfield <rj*@see.sig.invalidwrites:
>>CBFalconer said:
Richard Heathfield wrote:
CBFalconer said:
>
... snip ...
>>
>enum {OK = 0, NOMEM};
>
Are those the only two failure conditions? What about end of file?
Or a stream error? Why not make it possible to report those?

You didn't read the whole routine. It also returns EOF, which is
not defined here. I did point out that this listing omitted the
documentation etc.

Your point is well-taken, although it does seem that you fail to
distinguish between genuine end-of-file and a stream error.

So does fgets(). That's what feof() and ferror() are for.

[snip]

Nothing can be done about fgets but a new function /could/
disambiguate between these two conditions thus freeing the caller
from some more repetitive work.
Ridiculous. Most use of the function simply runs until a non-zero
is returned, after which the operation ends. It may be because of
EOF, or because of error. In either case, no further input is
available. If there is a need to distinguish EOF from errors, it
can be done at that point.

This is not a matter of correctness, but of design philosophy.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #17
On 30 May 2008 at 21:53, CBFalconer wrote:
Ridiculous. Most use of the function simply runs until a non-zero
is returned, after which the operation ends. It may be because of
EOF, or because of error. In either case, no further input is
available.
If you're in a restaurant and can't get your meal either because they've
run out of salmon or because the kitchen's on fire, you might find it
useful to be able to distinguish between those two error conditions.

Jun 27 '08 #18
rio
"CBFalconer" <cb********@yahoo.comha scritto nel messaggio #include
<stdio.h>
#include <stdlib.h>
#include "ggets.h"

#define INITSIZE 112 /* power of 2 minus 16, helps malloc */
#define DELTASIZE (INITSIZE + 16)

enum {OK = 0, NOMEM};
#define OK 0
#define NOMEM 1
#define EOF 2
#define EOFOK 4
int fggets(char* *ln, FILE *f)
{
int cursize, ch, ix;
char *buffer, *temp;

*ln = NULL; /* default */
if(ln==0||f==0) return ERROR;

if there is an error: better segfault
but if there is a segfault: better return error
All functions have to do the 'possible' for not seg fault in them
if (NULL == (buffer = malloc(INITSIZE))) return NOMEM;
cursize = INITSIZE;

ix = 0;
while ((EOF != (ch = getc(f))) && ('\n' != ch)) {
if (ix >= (cursize - 1)) { /* extend buffer */
cursize += DELTASIZE;
"jump if "+=" overflow -error"
if (NULL == (temp = realloc(buffer, (size_t)cursize))) {
/* ran out of memory, return partial line */
buffer[ix] = '\0';
*ln = buffer;
return NOMEM;
}
buffer = temp;
}
buffer[ix++] = ch;
}
if ((EOF == ch) && (0 == ix)) {
free(buffer);
return EOF;
return ferror(f)? EOF: EOFOK;
}
buffer[ix] = '\0';
if (NULL == (temp = realloc(buffer, (size_t)ix + 1))) {
*ln = buffer; /* without reducing it */
}
else *ln = temp;
return OK;
return ch==EOF? (ferror(f)?EOF:EOFOK) : OK;
Why not signal the EOF?
} /* fggets */
/* End of ggets.c */



Jun 27 '08 #19
CBFalconer wrote:
santosh wrote:
>Keith Thompson wrote:
>>Richard Heathfield <rj*@see.sig.invalidwrites:
CBFalconer said:
Richard Heathfield wrote:
>CBFalconer said:
>>
... snip ...
>>>
>>enum {OK = 0, NOMEM};
>>
>Are those the only two failure conditions? What about end of
>file? Or a stream error? Why not make it possible to report
>those?
>
You didn't read the whole routine. It also returns EOF, which is
not defined here. I did point out that this listing omitted the
documentation etc.

Your point is well-taken, although it does seem that you fail to
distinguish between genuine end-of-file and a stream error.

So does fgets(). That's what feof() and ferror() are for.

[snip]

Nothing can be done about fgets but a new function /could/
disambiguate between these two conditions thus freeing the caller
from some more repetitive work.

Ridiculous. Most use of the function
I was not talking about ggets in particular, but instead about a line
reading function in general.
simply runs until a non-zero
is returned, after which the operation ends. It may be because of
EOF, or because of error. In either case, no further input is
available. If there is a need to distinguish EOF from errors, it
can be done at that point.
C provides standard functions to disambiguate between end-of-file and
error. The relevant functions need to be called right after fgetc has
returned EOF. I think it's mostly a matter of design whether this is
done at all, and if so, whether in the caller or callee.

I don't what's ridiculous about any of these alternatives.
This is not a matter of correctness, but of design philosophy.
Yes. So characterising an alternative design as "ridiculous" might be a
bit premature.

Jun 27 '08 #20
Antoninus Twink wrote:
On 30 May 2008 at 21:53, CBFalconer wrote:
>Ridiculous. Most use of the function simply runs until a non-zero
is returned, after which the operation ends. It may be because of
EOF, or because of error. In either case, no further input is
available.

If you're in a restaurant and can't get your meal either because
they've run out of salmon or because the kitchen's on fire, you might
find it useful to be able to distinguish between those two error
conditions.
For some reason that is beound me you elected to ignore CBF's next sentence,
which addresses exaclty that:
>>If there is a need to distinguish EOF from errors, it
can be done at that point.
In you analogy: just ask the waiter for the reason or listen to the fire
alarm.

Bye, Jojo

Jun 27 '08 #21
Joachim Schmitz wrote:
Antoninus Twink wrote:
>On 30 May 2008 at 21:53, CBFalconer wrote:
>>Ridiculous. Most use of the function simply runs until a non-zero
is returned, after which the operation ends. It may be because of
EOF, or because of error. In either case, no further input is
available.

If you're in a restaurant and can't get your meal either because
they've run out of salmon or because the kitchen's on fire, you might
find it useful to be able to distinguish between those two error
conditions.
For some reason that is beound me you elected to ignore CBF's next
sentence, which addresses exaclty that:
>>>If there is a need to distinguish EOF from errors, it
can be done at that point.
The debate was whether the caller or the callee should disambiguate
between end-of-file and error. IMHO doing it in the caller saves a
small amount of otherwise extra work in the calling code, which is
after all, the main purpose of library code. It's unclear from the
above sentence by CBFalconer whether he means the caller or the callee
when he says "at that point". One might assume from the general tone of
his reply and the use of the word "ridiculous" that he prefers this to
be done by the calling code. Either way is fine but I personally prefer
to have the line reading function do this low-level chore.
In you analogy: just ask the waiter for the reason or listen to the
fire alarm.
The analogy is flawed. The client (line reading function) has to report
the reason to someone else, (perhaps someone at his home). So should
the client ask the waiter for the reason and go home and report that,
or go home and simply say "the salmon was unavailable" and leave it to
that person to go to the restaurant and ask the waiter for the reason
why Salmon was not available?

Jun 27 '08 #22
santosh wrote:
Joachim Schmitz wrote:
>Antoninus Twink wrote:
>>On 30 May 2008 at 21:53, CBFalconer wrote:
Ridiculous. Most use of the function simply runs until a non-zero
is returned, after which the operation ends. It may be because of
EOF, or because of error. In either case, no further input is
available.

If you're in a restaurant and can't get your meal either because
they've run out of salmon or because the kitchen's on fire, you
might find it useful to be able to distinguish between those two
error conditions.
For some reason that is beound me you elected to ignore CBF's next
sentence, which addresses exaclty that:
>>>If there is a need to distinguish EOF from errors, it
can be done at that point.

The debate was whether the caller or the callee should disambiguate
between end-of-file and error. IMHO doing it in the caller saves a
small amount of otherwise extra work in the calling code, which is
after all, the main purpose of library code. It's unclear from the
above sentence by CBFalconer whether he means the caller or the callee
when he says "at that point". One might assume from the general tone
of his reply and the use of the word "ridiculous" that he prefers
this to be done by the calling code. Either way is fine but I
personally prefer to have the line reading function do this low-level
chore.
>In you analogy: just ask the waiter for the reason or listen to the
fire alarm.

The analogy is flawed. The client (line reading function) has to
s/has/may have/
report the reason to someone else, (perhaps someone at his home). So
should the client ask the waiter for the reason and go home and
report that, or go home and simply say "the salmon was unavailable"
and leave it to that person to go to the restaurant and ask the
waiter for the reason why Salmon was not available?
Either is fine and at the discretion of the client (customer).
If someone else (at home) needs to know and the client didn't bother to ask,
that someone else better uses a different client next time.

Bye, Jojo
Jun 27 '08 #23
Joachim Schmitz wrote:
santosh wrote:
>Joachim Schmitz wrote:
>>Antoninus Twink wrote:
On 30 May 2008 at 21:53, CBFalconer wrote:
Ridiculous. Most use of the function simply runs until a non-zero
is returned, after which the operation ends. It may be because of
EOF, or because of error. In either case, no further input is
available.

If you're in a restaurant and can't get your meal either because
they've run out of salmon or because the kitchen's on fire, you
might find it useful to be able to distinguish between those two
error conditions.
For some reason that is beound me you elected to ignore CBF's next
sentence, which addresses exaclty that:
If there is a need to distinguish EOF from errors, it
can be done at that point.

The debate was whether the caller or the callee should disambiguate
between end-of-file and error. IMHO doing it in the caller saves a
small amount of otherwise extra work in the calling code, which is
after all, the main purpose of library code. It's unclear from the
above sentence by CBFalconer whether he means the caller or the
callee when he says "at that point". One might assume from the
general tone of his reply and the use of the word "ridiculous" that
he prefers this to be done by the calling code. Either way is fine
but I personally prefer to have the line reading function do this
low-level chore.
>>In you analogy: just ask the waiter for the reason or listen to the
fire alarm.

The analogy is flawed. The client (line reading function) has to
s/has/may have/
>report the reason to someone else, (perhaps someone at his home). So
should the client ask the waiter for the reason and go home and
report that, or go home and simply say "the salmon was unavailable"
and leave it to that person to go to the restaurant and ask the
waiter for the reason why Salmon was not available?
Either is fine and at the discretion of the client (customer).
If someone else (at home) needs to know and the client didn't bother
to ask, that someone else better uses a different client next time.
To extend the anaoly: If I go to a restaurant to eat and nothing is
available, I may not care why, the fact that I'm still hungry will just lead
me to the next restaurant.
Or I might care to ask why no salmon ia available and it the reason is a
burning kitchen, I'd leave hungry too (and quicly), otherwise I might pick a
diferent choice from the menu. Provided it's not the salmon that I'm
longinhg for.

So there are good reasons for both designs, both with pros and cons, but
none invalid or superior to the other.

Bye, Jojo
Jun 27 '08 #24
Joachim Schmitz wrote:
Joachim Schmitz wrote:
>santosh wrote:
>>Joachim Schmitz wrote:

Antoninus Twink wrote:
On 30 May 2008 at 21:53, CBFalconer wrote:
>Ridiculous. Most use of the function simply runs until a
>non-zero
>is returned, after which the operation ends. It may be because
>of
>EOF, or because of error. In either case, no further input is
>available.
>
If you're in a restaurant and can't get your meal either because
they've run out of salmon or because the kitchen's on fire, you
might find it useful to be able to distinguish between those two
error conditions.
For some reason that is beound me you elected to ignore CBF's next
sentence, which addresses exaclty that:
>If there is a need to distinguish EOF from errors, it
>can be done at that point.

The debate was whether the caller or the callee should disambiguate
between end-of-file and error. IMHO doing it in the caller saves a
small amount of otherwise extra work in the calling code, which is
after all, the main purpose of library code. It's unclear from the
above sentence by CBFalconer whether he means the caller or the
callee when he says "at that point". One might assume from the
general tone of his reply and the use of the word "ridiculous" that
he prefers this to be done by the calling code. Either way is fine
but I personally prefer to have the line reading function do this
low-level chore.

In you analogy: just ask the waiter for the reason or listen to the
fire alarm.

The analogy is flawed. The client (line reading function) has to
s/has/may have/
>>report the reason to someone else, (perhaps someone at his home). So
should the client ask the waiter for the reason and go home and
report that, or go home and simply say "the salmon was unavailable"
and leave it to that person to go to the restaurant and ask the
waiter for the reason why Salmon was not available?
Either is fine and at the discretion of the client (customer).
If someone else (at home) needs to know and the client didn't bother
to ask, that someone else better uses a different client next time.
To extend the anaoly: If I go to a restaurant to eat and nothing is
available, I may not care why, the fact that I'm still hungry will
just lead me to the next restaurant.
Or I might care to ask why no salmon ia available and it the reason is
a burning kitchen, I'd leave hungry too (and quicly), otherwise I
might pick a diferent choice from the menu. Provided it's not the
salmon that I'm longinhg for.

So there are good reasons for both designs, both with pros and cons,
but none invalid or superior to the other.
I agree. That is why I still don't understand why CBFalconer responded
to an earlier post as "ridiculous".

Jun 27 '08 #25
Joachim Schmitz wrote:
santosh wrote:
>Joachim Schmitz wrote:
>>Antoninus Twink wrote:
On 30 May 2008 at 21:53, CBFalconer wrote:
Ridiculous. Most use of the function simply runs until a non-zero
is returned, after which the operation ends. It may be because of
EOF, or because of error. In either case, no further input is
available.

If you're in a restaurant and can't get your meal either because
they've run out of salmon or because the kitchen's on fire, you
might find it useful to be able to distinguish between those two
error conditions.
For some reason that is beound me you elected to ignore CBF's next
sentence, which addresses exaclty that:
If there is a need to distinguish EOF from errors, it
can be done at that point.

The debate was whether the caller or the callee should disambiguate
between end-of-file and error. IMHO doing it in the caller saves a
small amount of otherwise extra work in the calling code, which is
after all, the main purpose of library code. It's unclear from the
above sentence by CBFalconer whether he means the caller or the
callee when he says "at that point". One might assume from the
general tone of his reply and the use of the word "ridiculous" that
he prefers this to be done by the calling code. Either way is fine
but I personally prefer to have the line reading function do this
low-level chore.
>>In you analogy: just ask the waiter for the reason or listen to the
fire alarm.

The analogy is flawed. The client (line reading function) has to
s/has/may have/
>report the reason to someone else,
Why? If a library function /could/ fail, then returning a status code is
IMHO more or less essential. Otherwise the function becomes close to
ususable.

<snip>

Jun 27 '08 #26
santosh wrote:
Joachim Schmitz wrote:
>santosh wrote:
>>Joachim Schmitz wrote:

Antoninus Twink wrote:
On 30 May 2008 at 21:53, CBFalconer wrote:
>Ridiculous. Most use of the function simply runs until a
>non-zero is returned, after which the operation ends. It may be
>because of EOF, or because of error. In either case, no further
>input is available.
>
If you're in a restaurant and can't get your meal either because
they've run out of salmon or because the kitchen's on fire, you
might find it useful to be able to distinguish between those two
error conditions.
For some reason that is beound me you elected to ignore CBF's next
sentence, which addresses exaclty that:
>If there is a need to distinguish EOF from errors, it
>can be done at that point.

The debate was whether the caller or the callee should disambiguate
between end-of-file and error. IMHO doing it in the caller saves a
small amount of otherwise extra work in the calling code, which is
after all, the main purpose of library code. It's unclear from the
above sentence by CBFalconer whether he means the caller or the
callee when he says "at that point". One might assume from the
general tone of his reply and the use of the word "ridiculous" that
he prefers this to be done by the calling code. Either way is fine
but I personally prefer to have the line reading function do this
low-level chore.

In you analogy: just ask the waiter for the reason or listen to the
fire alarm.

The analogy is flawed. The client (line reading function) has to
s/has/may have/
>>report the reason to someone else,

Why? If a library function /could/ fail, then returning a status code
is IMHO more or less essential. Otherwise the function becomes close
to ususable.
The client, your funktion, _may_ need to report failure to someone else.
The (Standard) Library indeed has to keep the reason some place.

Bye, Jojo
Jun 27 '08 #27
santosh wrote:
Joachim Schmitz wrote:
>Joachim Schmitz wrote:
>>santosh wrote:
Joachim Schmitz wrote:

Antoninus Twink wrote:
>On 30 May 2008 at 21:53, CBFalconer wrote:
>>Ridiculous. Most use of the function simply runs until a
>>non-zero
>>is returned, after which the operation ends. It may be because
>>of
>>EOF, or because of error. In either case, no further input is
>>available.
>>
>If you're in a restaurant and can't get your meal either because
>they've run out of salmon or because the kitchen's on fire, you
>might find it useful to be able to distinguish between those two
>error conditions.
For some reason that is beound me you elected to ignore CBF's next
sentence, which addresses exaclty that:
>>If there is a need to distinguish EOF from errors, it
>>can be done at that point.

The debate was whether the caller or the callee should disambiguate
between end-of-file and error. IMHO doing it in the caller saves a
small amount of otherwise extra work in the calling code, which is
after all, the main purpose of library code. It's unclear from the
above sentence by CBFalconer whether he means the caller or the
callee when he says "at that point". One might assume from the
general tone of his reply and the use of the word "ridiculous" that
he prefers this to be done by the calling code. Either way is fine
but I personally prefer to have the line reading function do this
low-level chore.

In you analogy: just ask the waiter for the reason or listen to
the fire alarm.

The analogy is flawed. The client (line reading function) has to
s/has/may have/

report the reason to someone else, (perhaps someone at his home).
So should the client ask the waiter for the reason and go home and
report that, or go home and simply say "the salmon was unavailable"
and leave it to that person to go to the restaurant and ask the
waiter for the reason why Salmon was not available?
Either is fine and at the discretion of the client (customer).
If someone else (at home) needs to know and the client didn't bother
to ask, that someone else better uses a different client next time.
To extend the anaoly: If I go to a restaurant to eat and nothing is
available, I may not care why, the fact that I'm still hungry will
just lead me to the next restaurant.
Or I might care to ask why no salmon ia available and it the reason
is a burning kitchen, I'd leave hungry too (and quicly), otherwise I
might pick a diferent choice from the menu. Provided it's not the
salmon that I'm longinhg for.

So there are good reasons for both designs, both with pros and cons,
but none invalid or superior to the other.

I agree. That is why I still don't understand why CBFalconer responded
to an earlier post as "ridiculous".
Indeed. Calling another ones opinion or needs ridiculous is just that...

Bye, Jojo
Jun 27 '08 #28
santosh said:
Joachim Schmitz wrote:
<snip>
>>
So there are good reasons for both designs, both with pros and cons,
but none invalid or superior to the other.

I agree. That is why I still don't understand why CBFalconer responded
to an earlier post as "ridiculous".
For a considerable number of months, Chuck's responses have been degrading
in quality. Recently, for example, he suggested that strspn is a
non-standard function - which, as any self-respecting C programmer ought
to know, really /is/ ridiculous.

He still gets stuff right occasionally, and I even think it's still
possible to hold a reasonable discussion with him, but it's getting more
difficult all the time.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 27 '08 #29
In article <sl*******************@nospam.invalid>,
Antoninus Twink <no****@nospam.invalidwrote:
>Ridiculous. Most use of the function simply runs until a non-zero
is returned, after which the operation ends. It may be because of
EOF, or because of error. In either case, no further input is
available.
>If you're in a restaurant and can't get your meal either because they've
run out of salmon or because the kitchen's on fire, you might find it
useful to be able to distinguish between those two error conditions.
On the other hand, I've been to hundreds of restaurants and have on
several occasions had to make a new choice because they'd run out of
what I'd ordered, but I've never had the problem that their kitchen
was on fire. It's not a possibility that I take into account when
choosing restaurants. Similarly, for some purposes the possibility of
an i/o error while reading is so insignificant that it can just be
ignored - just as you typically take no precautions to guard against
out-of-stack errors (which in my experience are much more common).

Obviously a program which, say, deletes the original file after
processing it should distinguish between an i/o error and EOF.
But not all programs are like that, and typically an i/o error
will produce a user-visible indication.

Errors when writing, rather than reading, are much more common because
they can be caused by a full disk.

-- Richard
--
In the selection of the two characters immediately succeeding the numeral 9,
consideration shall be given to their replacement by the graphics 10 and 11 to
facilitate the adoption of the code in the sterling monetary area. (X3.4-1963)
Jun 27 '08 #30
santosh wrote:
Joachim Schmitz wrote:
.... snip ...
>
>So there are good reasons for both designs, both with pros and
cons, but none invalid or superior to the other.

I agree. That is why I still don't understand why CBFalconer
responded to an earlier post as "ridiculous".
Because complicating a simple routine to allow for 'everything' is
ridiculous, especially when no impediment has been placed in the
way of handling that 'everything' when needed. Also, this is a
binary world, so many things go on the 'ridiculous' side to me.
:-)

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #31
rio wrote, On 31/05/08 06:51:
"CBFalconer" <cb********@yahoo.comha scritto nel messaggio #include
<stdio.h>
>#include <stdlib.h>
#include "ggets.h"

#define INITSIZE 112 /* power of 2 minus 16, helps malloc */
#define DELTASIZE (INITSIZE + 16)

enum {OK = 0, NOMEM};

#define OK 0
#define NOMEM 1
#define EOF 2
Rather problematic seeing as stdlib.h already defines EOF
#define EOFOK 4
>int fggets(char* *ln, FILE *f)
{
int cursize, ch, ix;
char *buffer, *temp;

*ln = NULL; /* default */

if(ln==0||f==0) return ERROR;

if there is an error: better segfault
but if there is a segfault: better return error
The above two statements seem to directly contradict each other so I'm
not sure what you are trying to say.

<snip>
--
Flash Gordon
Jun 27 '08 #32
rio

"Flash Gordon" <sp**@flash-gordon.me.ukha scritto nel messaggio
news:qe************@news.flash-gordon.me.uk...
rio wrote, On 31/05/08 06:51:
>"CBFalconer" <cb********@yahoo.comha scritto nel messaggio #include
if there is an error: better segfault
but if there is a segfault: better return error

The above two statements seem to directly contradict each other so I'm not
sure what you are trying to say.
if there is an data error in a function is better
segfault the function
but
is *much better* [than seg fault] the function return an error value
<snip>
--
Flash Gordon


Jun 27 '08 #33
rio wrote:
"Flash Gordon" <sp**@flash-gordon.me.ukha scritto nel messaggio
news:qe************@news.flash-gordon.me.uk...
>rio wrote, On 31/05/08 06:51:
>>"CBFalconer" <cb********@yahoo.comha scritto nel messaggio >
#include if there is an error: better segfault
but if there is a segfault: better return error

The above two statements seem to directly contradict each other so
I'm not sure what you are trying to say.

if there is an data error in a function is better
segfault the function
but
is *much better* [than seg fault] the function return an error value
A segvault might be better han continue processing with bogus data but
better than a segvault is an assert(), as it would easily tell you in which
file and line the error occured, rather than having you to run it thru a
debugger to find some stack trace. Also0 a segvault might not give you what
you need to debug, e.g. if the stack itself got corrupted.
But still a segvault as well as a failed assertion is a bug in the program
IMHO.

Bye, Jojo
Jun 27 '08 #34
santosh <sa*********@gmail.comwrites:
CBFalconer wrote:
>santosh wrote:
>>Keith Thompson wrote:
Richard Heathfield <rj*@see.sig.invalidwrites:
CBFalconer said:
>Richard Heathfield wrote:
>>CBFalconer said:
>>>
>... snip ...
>>>>
>>>enum {OK = 0, NOMEM};
>>>
>>Are those the only two failure conditions? What about end of
>>file? Or a stream error? Why not make it possible to report
>>those?
>>
>You didn't read the whole routine. It also returns EOF, which is
>not defined here. I did point out that this listing omitted the
>documentation etc.
>
Your point is well-taken, although it does seem that you fail to
distinguish between genuine end-of-file and a stream error.

So does fgets(). That's what feof() and ferror() are for.

[snip]

Nothing can be done about fgets but a new function /could/
disambiguate between these two conditions thus freeing the caller
from some more repetitive work.

Ridiculous. Most use of the function

I was not talking about ggets in particular, but instead about a line
reading function in general.
>simply runs until a non-zero
is returned, after which the operation ends. It may be because of
EOF, or because of error. In either case, no further input is
available. If there is a need to distinguish EOF from errors, it
can be done at that point.

C provides standard functions to disambiguate between end-of-file and
error. The relevant functions need to be called right after fgetc has
returned EOF. I think it's mostly a matter of design whether this is
done at all, and if so, whether in the caller or callee.

I don't what's ridiculous about any of these alternatives.
>This is not a matter of correctness, but of design philosophy.

Yes. So characterising an alternative design as "ridiculous" might be a
bit premature.
You must remember that "Chuck" is a world authority on everything and
has publicly stated that it would hard to find "better" than his
libraries...

Jun 27 '08 #35
CBFalconer wrote:
santosh wrote:
>Joachim Schmitz wrote:
... snip ...
>>
>>So there are good reasons for both designs, both with pros and
cons, but none invalid or superior to the other.

I agree. That is why I still don't understand why CBFalconer
responded to an earlier post as "ridiculous".

Because complicating a simple routine to allow for 'everything' is
ridiculous,
Actually the function only has to return one additional status code, but
yes, point taken.
especially when no impediment has been placed in the
way of handling that 'everything' when needed. Also, this is a
binary world, so many things go on the 'ridiculous' side to me.
:-)
I noticed.

Jun 27 '08 #36
Joachim Schmitz wrote:

<snip>
A segvault might be better han continue processing with bogus data but
better than a segvault is an assert(), as it would easily tell you in
which file and line the error occured, rather than having you to run
it thru a debugger to find some stack trace.
Also behaviour on an assertion failure is defined by the standard while
a segfault is not guaranteed to occur on all platforms.

<snip>

Jun 27 '08 #37
santosh <sa*********@gmail.comwrites:
Joachim Schmitz wrote:
[...]
>In you analogy: just ask the waiter for the reason or listen to the
fire alarm.

The analogy is flawed. The client (line reading function) has to report
the reason to someone else, (perhaps someone at his home). So should
the client ask the waiter for the reason and go home and report that,
or go home and simply say "the salmon was unavailable" and leave it to
that person to go to the restaurant and ask the waiter for the reason
why Salmon was not available?
Speaking of flawed analogies ...

I don't think the difference is all that big a deal. You're not going
home, then going back to the restaurant to ask whether it's on fire.
It's just a difference between (a) getting a result back from the
input function that tells you whether and how it failed, or (b)
getting a result back from the input function that tells you it
failed, then calling another (presumably very cheap) function to tell
you why.

(On the other hand, separating the error determination this way does
make it too easy to ignore error conditions. The most straightforward
idioms for reading from a file just read until they can't, then stop.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #38
"rio" <a@b.cwrites:
"Flash Gordon" <sp**@flash-gordon.me.ukha scritto nel messaggio
news:qe************@news.flash-gordon.me.uk...
>rio wrote, On 31/05/08 06:51:
>>"CBFalconer" <cb********@yahoo.comha scritto nel messaggio #include
if there is an error: better segfault
but if there is a segfault: better return error

The above two statements seem to directly contradict each other so I'm not
sure what you are trying to say.

if there is an data error in a function is better
segfault the function
but
is *much better* [than seg fault] the function return an error value
"rio", are you the same person who previously posted as
"RoSsIaCrIiLoIA" and as "av <av@ala.a>"?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #39
Keith Thompson wrote:
>
"rio" <a@b.cwrites:
.... snip ...
>
>if there is an data error in a function is better segfault the
function but is *much better* [than seg fault] the function
return an error value

"rio", are you the same person who previously posted as
"RoSsIaCrIiLoIA" and as "av <av@ala.a>"?
I doubt it. He isn't pushing stupid obfuscative macros.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
** Posted from http://www.teranews.com **
Jun 27 '08 #40
santosh wrote:
Joachim Schmitz wrote:

<snip>
>A segvault might be better han continue processing with bogus data
but better than a segvault is an assert(), as it would easily tell
you in which file and line the error occured, rather than having you
to run it thru a debugger to find some stack trace.

Also behaviour on an assertion failure is defined by the standard
while a segfault is not guaranteed to occur on all platforms.
And that is indeed another why I regard an assert() better than a segfault.
I just forgot to mention.

Bye, Jojo
Jun 27 '08 #41

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

Similar topics

9
by: WL | last post by:
Hey, all. I'm creating an array of strings (char **argv style) on the fly, and using realloc to create string pointers, and malloc for the strings itself (if that makes any sense). I'm using the...
7
by: Rano | last post by:
/* Hello, I've got some troubles with a stupid program... In fact, I just start with the C language and sometime I don't understand how I really have to use malloc. I've readden the FAQ...
50
by: Joseph Casey | last post by:
Greetings. I have read that the mistake of calling free(some_ptr) twice on malloc(some_data) can cause program malfunction. Why is this? With thanks. Joseph Casey.
6
by: I_have_nothing | last post by:
Hi! I am new in C. I try to use dynamical allocation fuction malloc( ) and realloc( ). I found something strange. After several calling realloc( ), the malloc( ) will give me a Segmentation...
27
by: ncf | last post by:
Hi all. In another topic, I was informed that I had to dynamically allocate memory instead of just trying to expand on a list. (I'm trying to learn C, and have a strong background in PHP and...
24
by: Hrv'uljak | last post by:
Anybody has a better solution? How to avoid memory allocation in main function? Thanks! -------- #include <stdio.h> #include <conio.h> #include <string.h> #include <malloc.h>
82
by: quiberon2 | last post by:
Hi, Sorry if it might be a stupid question but what should returns malloc(0) ? void *ptr = malloc(0); I am running gcc 3.3.5 and a non-null address is returned. ( in the compiler that I am...
37
by: ravi.cs.2001 | last post by:
Hi all, I m relatively new to C. I have few queries related to malloc(): #1. When we perform malloc(), the memory allocated dynamically comes from the heap area of the process in concern....
26
by: Muzammil | last post by:
whats the beauty of "malloc" over "new" why its helpful for programmer.for its own memory area.??
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

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.