Subject: Re: Possible bug relating to malloc()/realloc(), popen(), and read()
To: None <port-i386@NetBSD.org>
From: Vincent Stemen <netbsd@crel.us>
List: port-i386
Date: 12/02/2004 12:46:12
Thanks for your feedback everybody.


On Thu, Dec 02, 2004 at 10:23:57AM -0500, der Mouse wrote:
> 
> Here is your actual problem.
> 
> You need to move this bufp += bytes_read outside the if (ie, swap this
> line with the next line).  Otherwise, you are failing to advance your
> buffer pointer unless the read reads a whole block_size bytes, so of
> _course_ it will be reading over previously read data.
> 
> Also, since you always try to read block_size bytes, you need to
> realloc not when count==block_size but rather whenever
> bytes_read+block_size is greater than the amount of memory you
> currently have (which you don't keep anywhere) - ie, you need to make
> sure you have at least block_size bytes for the next read to read into.
> What do you have against using stdio?

Ok.  I thought it would always ready the full block_size unless it ran
into EOF or got an error.  Apparently I cannot depend on that due to
buffering issues when reading from a network pipe as in popen.

> What do you have against using stdio?

Nothing.  The common consensus here is that it would be better to use
stdio and I tend to agree.  In fact I was already thinking seriously
about re-writing it using stdio before I saw your replies.

To be honest, I was still unclear about the advantages/disadvantages
of read() vs fread() at first, and read() seemed like a little simpler
to use (simpler arguments and no separate calls to feof() and
ferror()).  However, with further research, I now understand the
buffering advantages of stdio in applications such as this.

> Leaving aside the question of using stdio or not, I'd write that as
> something like this:
> 
>  /* I consider NULL harmful;

I am curious why you consider NULL harmful?


>     I also consider gratuitous embedded assignments harmful. */
>  output = malloc(block_size);
>  if (output == 0) { ...can't malloc... }

That is an interesting comment.  It seems like coding examples almost
always show embedded return value assignments and I often find it
convenient in looping.  How do you consider it harmful?

You guys are right.  It is overwriting the first block of data since I
am not bumping the pointer if it reads less than the full block size.

What I still am not clear about is:
    Why does it consistently read only 1024 bytes only on the first
    read and then always read the full specified block size on all
    subsequent reads.

    Why does it not do that on FreeBSD?  This is one of the things
    that made me wonder if there was a bug in NetBSD.

    Also, why does the problem not exist when I run it through the
    debugger (gdb).  In that case it always seems to read the full
    specified block size, even on the first read if I step through it.
    If I let it run at normal speed through the first two reads, it
    still only reads 1024 bytes on the first read.  It is apparently
    timing related.

-- 
Vincent Stemen
Avoid the VeriSign/Network Solutions domain registration trap!
Read how Network Solutions (NSI) was involved in stealing our domain name.
http://www.InetAddresses.net