2

Been given the task to convert code from the 80's to 64 bit.

Error given error: size of array "spare2" is too large

This is line 76 of a header file

Line 76 uchar spare2[1018-XVIEWS*sizeof(view)-4*12] ;

Full Block


#define XVIEWS  25        /* max would be 26.9          */

typedef struct { struct {
    rec_noi root        ; /* seqtree root           */
    ushort  nlevels     ; /* # levels in seqtree        */

#if LALIGN
    ushort  del_head    ; /* [al] wunaligned long       */
    ushort  del_head2   ;
    ushort  ndel        ; /* [al] ditto             */
    ushort  ndel2       ;
#else
    ulong   del_head    ; /* first deleted seq# + 1     */
                  /* (0 or 0x0FFFFFFF if none)      */
    ulong   ndel        ; /* # deleted seq#s            */
#endif
                  /* remainder of record is waligned    */
    uchar   flags       ; /* bitfield set with DCRF_values  */
    bool1   tobedeleted ; /* database to be deleted?        */
    rec_no  idr[4]      ; /* list of: index defn records    */
    rec_no  irtab       ; /* irule record chain head        */
    ulong   spare1      ; /* help yourself          */
    rec_no  viewselect  ; /* view selection record      */
    view    V[XVIEWS]   ; /* view information           */
    rec_no  vcont       ; /* view continuation record       */
    uchar   spare2[1018-XVIEWS*sizeof(view)-4*12] ;
    } DCRREC ; } dcrrec ;

Tried gcc -g -march=x86-64 -v file.c -o file.o -Wl,--heap,SIZE

But no matter what I try to change the heap size to, I keep getting the same the same error. I also tried changing heap to stack and both heap and stack. No change.

Should I be doing something else?

EDIT: I found out I left out another important piece of information. I am currently trying to figure out what is rec_no


typedef struct view {
    rec_no  canuse      ; /* master DDB index #'s in use record */
                  /* view:  fields allowed from view    */
    rec_no  permission  ; /* permission record          */
    rec_no  symrec      ; /* sym def rec fdrid          */
    rec_no  objrec      ; /* allowed function list      */
                  /*    (currently -> vdr)      */
    uchar   dbname[12]  ; /* database name (BASIC string)   */
    rec_no  autoglo     ; /* autoglobal record          */
    rec_no  sttab       ; /* storage rule table chain head  */
    } view ;```
5
  • 5
    Haven't done the math but that expression is going to produce an unsigned value, if sizeof(view) is about 40 or more the size calculation is going to wrap to a very large positive number. Commented Sep 18 at 22:44
  • 11
    Where is the type view defined? Please post a Minimal Reproducible Example, the shortest complete code that shows the problem. Commented Sep 18 at 22:50
  • 3
    Style note: the nested structures declared in a single statement are gruesome. Don't do it! Commented Sep 18 at 23:20
  • Before changing the size of any fields, check whether you need to process data files created by the old code. If you do, you may need to change the version of the files that you write and support reading the old version to convert to the new form. Commented Sep 19 at 2:01
  • You need to get rid of all "magic numbers". Nobody wants to maintain code full of magic numbers. Commented Sep 19 at 6:24

2 Answers 2

12

The line uchar spare2[1018-XVIEWS*sizeof(view)-4*12]; is used to specify padding for the element size to be exactly 1018 bytes long.

The definitions of all types used in this fragment are not posted: rec_noi, rec_no, ushort, ulong, uchar, bool1 and view. ushort, uchar and ulong are probably self explanatory, but might hide some surprising definitions.

The problem is the view structure is larger on your 64-bit target than on the original system, and other fields are probably larger too as ulong may be 64-bit instead of 32 (as is the case on linux and macOS). The hard-coded computation evaluates to a negative quantity, which becomes a (very) large positive number because sizeof(view) has the unsigned type size_t (presumably 64-bit) and this makes the whole expression an unsigned value, hence the error message.

Porting this code to 64-bit may prove difficult: you might first try and change the types to fixed width types such as uint16_t and uint32_t to avoid architecture dependent sizes.

You can try and typedef ulong to uint32_t instead of unsigned long, but the code might use long too and you cannot easily change those with a typedef.

If the project is open sourced, you can post a link to the source code for more porting recommendations.

Sign up to request clarification or add additional context in comments.

2 Comments

The type view is not the only undefined type: rec_noi (probably a typo), rec_no and bool1. We can guess at what's in bool1 — but why not use C23 bool or C99-C18 _Bool, or bool again with the <stdbool.h> header. The other two might be simple numbers of 4 or 8 bytes (or possibly 2 bytes). Using the type names from <stddef.h> would be sensible. But, I agree that the array of view values is most probably the primary cause of structure inflation.
Changing ulong to uint32_t was the right answer
-1

The easiest fix is to turn the calculated size into a signed expression:

uchar   spare2[1018-XVIEWS*(int)sizeof(view)-4*12]; 
//                         *****

or for maximum safety in case XVIEWS gets converted to unsigned or something

uchar   spare2[ (int)( 1018-XVIEWS*sizeof(view)-4*12 ) ];

because unsigned-ness is sticky, for a given size if either operand is unsigned the result is unsigned. So uint+int will be uint, uint+long will be long if long has more bits, ulong if it doesn't. It's one of those quirks that made sense at the time and it's far, far too late to change it now, every choice has its downsides.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.