delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1999/09/17/19:33:02

Date: Sat, 18 Sep 1999 02:21:52 +0700
From: Batchex <thedark1 AT Phreaker DOT net>
X-Mailer: The Bat! (v1.32) S/N E34104EF
X-Priority: 3 (Normal)
Message-ID: <1498.990918@Phreaker.net>
To: "S. M. Halloran" <djgpp AT delorie DOT com>
Subject: Re[2]: invalid operands
In-reply-To: <199909150739.KAA00434@ankara.Foo.COM>
References: <199909150739 DOT KAA00434 AT ankara DOT Foo DOT COM>
Mime-Version: 1.0
Reply-To: djgpp AT delorie DOT com
X-Mailing-List: djgpp AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

Hi,

Wednesday, September 15, 1999, 4:44:31 PM, you wrote:

SMH> On 13 Sep 99, Batchex was found to have commented thusly:

>> Hi,
>>
>>   I have  a difficulty with the code below :
>>
>>   FILE *fp;
>>   int nIdx, nNumEntries;
>>   long lnDataStart, lnFileSize;
>>   char **lpszTable;
>>
>>   // clipped
>>
>>   lpszTable = (char **)malloc(nNumEntries*sizeof(char *));
>>   fread(lpszTable,sizeof(char *),nNumEntries,fp);

SMH> You've stored pointer in a file and believe that by loading them that they will
SMH> point where you want, as if memory addresses are burned into the application?
SMH> Or is fp just a reference to another type of dynamic data storage object, i.e.,
SMH> really memory?

fp is a refference to file. No, I don't store pointers in the file,
just offsets to the beginning of each entries at the data areas in the
file.

>>   lnDataStart = (long)lpszTable[0];
SMH>                         ^^^^^^^^^^^^
SMH> Uninitialized value used in assignment.

After fread(), lpszTable[0] will store the offset of the begining of
the first entry.

>>   lpszTable[0] = (char *)malloc((lnFileSize-lnDataStart)*sizeof(char));
SMH>                                    ^^^^^^^^^^ ^^^^^^^^^^^

SMH> And now you initialize lpszTable[0] with the value lnDataStart, which was
SMH> itself initialized by lpszTable[0].  Even if it is something you wanted to do,
SMH> at the very least you should free lpszTable[0] first before assigning it a new
SMH> value.

lpszTable[0] is initialized with the address of an allocated mem with
size of filesize-headersize (the size of the actual data).

SMH> You are also doing pointer arithmetic without thinking about the values of the
SMH> pointers or integers created by those magic casts.  Casting pointers to
SMH> integers and back again are okay at times, and the compiler won't complain
SMH> because it assumes the programmer knows what he is doing when he uses casts in
SMH> a limited fashion.  Get out your debugger and put watches on lnFileSize,
SMH> lnDataStart, and the expression "lnFileSize-lnDataStart" and see if it is doing
SMH> what you expected.  You almost certainly will find it is not the case.  It's a
SMH> universally good idea, especially for people new to programming in C/C++, to
SMH> test always the pointer returned by an _alloc() function, to see if it is NULL
SMH> and to include hand-waving code in the condition that it is.

So far, I'm assuming that pointers in DJGPP is only offsets, b'cause
each segments is 4Gb long. I don't know if it is entirely safe to
assume that, but working with asm in pmode makes me believe my
assumption. I have tested the code under gdb, and it works just like I
wanted (except for the invalid operand part).

BTW, I don't include pointer checking for malloc here is to make the
code a few lines less, to keep my mail short. In the actual code, I
always test it.

SMH> How did you set your compilers warnings btw?  Make sure your warning levels are
SMH> set correctly, and handle [nearly] every warning as if it's a compiler error
SMH> (for some, those warnings *are* errors).

I'm compiling it with -Wall -g -O2.

>>   for(nIdx=1;nIdx<nNumEntries;nIdx++)
>>    lpszTable[nIdx]=(char *)(lpszTable[0]+(lpszTable[nIdx]-lnDataStart));

SMH> The operands are invalid because in your expression (char *)(x + (y - z)), the
SMH> addition of x (a pointer) is to another pointer (the evalution of y - z).  The
SMH> evaluation of y - z is valid in general, but not the way you used it here.

>>   NOTE : fp, nNumEntries & lnFileSize is initialized somewhere else
>>   before the above code.
>>
>>   The last line of the code always gives me "invalid operands for
>>   binary +". If lpszTable[0] is not malloc()ed before the for loop, it
>>   compiles and run fine. I have tried some variations for the
>>   assignment, and I think the lpszTable[0] operand is the culprit.
>>   What I need is to load some data to an allocated buffer, load the
>>   entries offsets to another allocated buffer ('cause the entries have
>>   variable lengths), then add the offsets to the address of the
>>   allocated data buffer (the first allocated buffer). How can I do
>>   this if adding lpszTable[0] with some value gives "invalid operands
>>   for binary +"?

SMH> The way they probably teach you in school is the following [set your message
SMH> line width to 80 chars on your mail reader]:

SMH>     1. Allocate block of memory to contain your pointers to memory which are
SMH>        offsets to your entries:

SMH>              if ((lpszTable = calloc(nNumEntries, sizeof(char *))) == NULL)
SMH>                  goto scream_nomem;  /* or scream_fatal_error("NOMEM") */

SMH>     2. For each entry, you now determine its size (number of chars plus a NUL
SMH>         byte if you intend to treat it as a NUL-terminated string) and then
SMH>         allocate:

SMH>           int size_of_entries = { BYTES_ENTRY_1, BYTES_ENTRY_2, /* ... */ };

SMH>           for (i = 0; i < nNumEntries; i++)
SMH>           {
SMH>              if ((lpszTable[i] = malloc((size_of_entries[i] + 1) *
SMH>                             sizeof(char))) == NULL)
SMH>                      goto scream_nomem;
SMH>               /* copy the chars into the allocd mem while you're at it */
SMH>           }

SMH>         If you are working with a file and you want to read it into one buffer
SMH>         and you know the offsets for each of the nNumEntries, then you can try:

SMH>          int my_offsets_from_start_of_buffer { OFFSET_1, OFFSET_2, /* ...*/};

SMH>          if ((lpszTable[0] = malloc(lnFileSize))) == NULL)
SMH>                         ;
SMH>          fread(lpszTable[0], 1, lnFileSize, fp);
SMH>          for (i = 1; i < nNumEntries; i++)
SMH>                         lpszTable[i] = lpszTable[0] + my_offsets_from_start_of_buffer[i];

SMH>          Note that mem is allocd as a block, and then you just set up the
SMH>          offsets from the address where the buffer starts using pointer
SMH>          addition.

SMH>          In either case you have to know what your offsets are or have a way
SMH>          of calculating them.

My code basically does the same thing (at least at algorithm level).
My data consist of 2 blocks, the first is the header, which is
consists of number of entries and the offsets to the beginning of each
entries in the file, the second is the data itself, aligned to double
word boundary. Looking to your 2nd step, loading the entire file to
mem, will be exceptable if number of entries is low, but if it is
high, like 128 and higher, more mem will be wasted (the offsets is 4
bytes long, thus 128 entries yields to 128*4=512 bytes). Consider
this, if the filesize is 2kb and number of entries is 128, then we
must allocate 2kb plus 128*4 for the offsets. My approach is allocate
mem just enough to store the data (2kb-128*4) and allocate 128*4 bytes
mem to store the offsets, which yield 2kb mem overall is used.

>>   One other question, not related to the above code, anybody know any
>>   function that can read raw data from file (like _dos_read()) that is
>>   POSIX compliant? fread() seems to stop whenever it encounter CR/LF
>>   pair ("\n"), and my data have a lot of them.

SMH> With DJGPP and most other systems, you can get that POSIX-compliant behavior by
SMH> using:

SMH>              if ((fp = fopen(myfilename, "rb"))) == NULL)
SMH>                   ;

SMH>    Note the flag "rb" for "read binary" whereas "r" is "read [text]".  You need
SMH> to do that as well with the open() Unix call:

SMH>      open(myfilename, O_RDONLY | O_BINARY)

SMH> Countless programming hours have been lost by novice and experienced alike
SMH> because of this idiosyncrasy.

SMH> Mitch Halloran
SMH> Research (Bio)chemist
SMH> Duzen Laboratories Group
SMH> Ankara       TURKEY

Batchex
mailto:thedark1 AT Phreaker DOT net


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019