www.digitalmars.com         C & C++   DMDScript  

c++ - Union bug??

reply Mark Evans <mevans zyvex.com> writes:
It's possible that I've uncovered a bug in the C compiler.

The complicated structure below includes a union of subsidiary structure types.
Given two of these ParseBlock structures, I want to copy one of the unionized
subsidiaries from one ParseBlock to the other.

It is turning out to be surprisingly close to impossible, and I don't understand
why.  This should be a simple memory operation.  The structures are declared
as __far in my 16-bit Windows 3.1 app.  The union is a union of structures
which are defined in a vendor header file.  These are identified as SPM_XXX
structs.

The only code that works copies the entire ParseBlock, including
the internal union.  (Here outpb and inpb are far pointers to ParseBlock.)

	*outpb = *inpb;

The following similar code does not work (but should):
	
	*((SPM_APPROACH_PARAMS __far *) &(outpb->structs.pb_SPM_APPROACH_PARAMS)) = 
	*((SPM_APPROACH_PARAMS __far *) &(inpb->structs.pb_SPM_APPROACH_PARAMS));

The more natural and expected fmemcpy() also fails:
	
	_fmemcpy(&(outpb->structs.pb_SPM_APPROACH_PARAMS),
		&(inpb->structs.pb_SPM_APPROACH_PARAMS),
		sizeof(SPM_APPROACH_PARAMS));

Does anyone have a clue what is going on?

Mark



typedef struct
{
    // locking flag and stack to indicate how it was
    // populated
    
    BOOL                    locked;

    // general atomic parameter storage
    unsigned long int       U32[k_PARSE_PARAM_ARRAY_SZ];
    unsigned short int      U16[k_PARSE_PARAM_ARRAY_SZ];
    signed long int         I32[k_PARSE_PARAM_ARRAY_SZ];
    signed short int        I16[k_PARSE_PARAM_ARRAY_SZ];
    float                   SGL[k_PARSE_PARAM_ARRAY_SZ];
    double                  DBL[k_PARSE_PARAM_ARRAY_SZ];
    char                    BLC[k_PARSE_PARAM_ARRAY_SZ];
    HSPM                    spmHandles[k_PARSE_PARAM_ARRAY_SMALL_SZ];   
    SPMERROR                spmErrs[k_PARSE_PARAM_ARRAY_SMALL_SZ];
    HWND                    window[k_PARSE_PARAM_ARRAY_SMALL_SZ];
    char __far             
STR[k_PARSE_PARAM_ARRAY_SMALL_SZ][k_PARSE_STRING_SZ];
        
    // next-free (also population count)
    signed long int         U32_slot,U16_slot,I32_slot,I16_slot,
                            SGL_slot,DBL_slot,spmHandles_slot,spmErrs_slot,
                            window_slot,BLC_slot,STR_slot;

    // output counters  
    signed long int         U32_outcnt,U16_outcnt,I32_outcnt,I16_outcnt,
                           
SGL_outcnt,DBL_outcnt,spmHandles_outcnt,spmErrs_outcnt,
                            window_outcnt,BLC_outcnt,STR_outcnt;
    // Arrays
    // Can be any dimension, data is contiguous, row-major order (C order)
    
    long int                arrayDimensionality;    // 1D, 2D, 3D, ...
    unsigned long int       arrayDims;              // the actual array sizes

    TypeCode arrayType; 
    union arrays
    {
        unsigned long int   __huge *    U32Ptr;
        unsigned short int  __huge *    U16Ptr;
        signed long int     __huge *    I32Ptr;
        signed short int    __huge *    I16Ptr;
        float               __huge *    SGLPtr;
        double              __huge *    DBLPtr;
    };

    // storage for pointers to structs for recursion
    TypeCode                recursionStack[k_PARSE_PARAM_ARRAY_SZ];
    unsigned long int       recursion;

    // Every struct type in spm.h, the Park API
    TypeCode structType;
    union
    {
        SPM_PARAMS                  pb_SPM_PARAMS;
        SPM_STATUS_ITEM             pb_SPM_STATUS_ITEM;
        SPM_CALIBRATE_PROGRESS      pb_SPM_CALIBRATE_PROGRESS;
        SPM_ERROR_SIGNAL            pb_SPM_ERROR_SIGNAL;
        SPM_SCANNER_Z               pb_SPM_SCANNER_Z;
        SPM_SCANNER_XY              pb_SPM_SCANNER_XY;
        SPM_SCANNER_Z_SLOPE         pb_SPM_SCANNER_Z_SLOPE;
        SPM_BIAS                    pb_SPM_BIAS;
        SPM_DATA_FILTER_PARAMS      pb_SPM_DATA_FILTER_PARAMS;
        SPM_STEP_PIECE              pb_SPM_STEP_PIECE;
        SPM_WAVE_PIECE              pb_SPM_WAVE_PIECE;
        SPM_WAVE_ACQ                pb_SPM_WAVE_ACQ;
        SPM_SCANNING_PARAMS         pb_SPM_SCANNING_PARAMS;
        SPM_SCAN_RATE_PARAMS        pb_SPM_SCAN_RATE_PARAMS;
        SPM_APPROACH_PARAMS         pb_SPM_APPROACH_PARAMS;
        SPM_APPROACH_PARAMS_LOW     pb_SPM_APPROACH_PARAMS_LOW;
        SPM_MOVE_STEPPER_PARAMS     pb_SPM_MOVE_STEPPER_PARAMS;
        SPM_STEPPER_PARAMS          pb_SPM_STEPPER_PARAMS;
        SPM_MOVE_IMOTOR_PARAMS      pb_SPM_MOVE_IMOTOR_PARAMS;
        SPM_MOVE_PC38_PARAMS        pb_SPM_MOVE_PC38_PARAMS;
        SPM_NCM_SWEEP_LOW_TYPE      pb_SPM_NCM_SWEEP_LOW_TYPE;
        SPM_NCM_PHOP_TYPE           pb_SPM_NCM_PHOP_TYPE;
        SPM_NCM_RESPONSE_LUT        pb_SPM_NCM_RESPONSE_LUT;
        SPM_VOLTAGE_PROBE_PARAMS    pb_SPM_VOLTAGE_PROBE_PARAMS;
        SPM_NCM_SWEEP_PARAMS        pb_SPM_NCM_SWEEP_PARAMS;
        SPM_NCM_SWEEP_POINT         pb_SPM_NCM_SWEEP_POINT;

    } structs;

} ParseBlock,  __far * ParseBlockPtr;
May 16 2001
parent reply Mark Evans <mevans zyvex.com> writes:
I may have discovered the problem.

ParseBlock __far		inpb_block, outpb_block;

declares one of the structs as far, the other near.  This was a mistake.

Mark
May 16 2001
parent reply Mark Evans <mevans zyvex.com> writes:
Still I would like to understand why the assignment *outpb = *inpb works when
one block is declared near, the other far.  And what is the doctor-recommended
method for copying between 
near and far data segments.  And how would I assign two far objects to the same
data segment.  I did not find a pragma for this purpose.

I tried chaning both to __far and some other code broke mysteriously.  Oh how I
love 16-bit code.

Mark



On Wed, 16 May 2001 21:26:39 GMT, Mark Evans <mevans zyvex.com> wrote:
 I may have discovered the problem.
 
 ParseBlock __far		inpb_block, outpb_block;
 
 declares one of the structs as far, the other near.  This was a mistake.
 
 Mark
 
 

May 16 2001
parent reply "Walter" <walter digitalmars.com> writes:
It all depends on your memory model. I'd use _fmemcpy() if in a near data
model, and memcpy() in a far data model.


"Mark Evans" <mevans zyvex.com> wrote in message
news:1106_990055289 evans...
 Still I would like to understand why the assignment *outpb = *inpb works

doctor-recommended method for copying between
 near and far data segments.  And how would I assign two far objects to the

 I tried chaning both to __far and some other code broke mysteriously.  Oh

 Mark



 On Wed, 16 May 2001 21:26:39 GMT, Mark Evans <mevans zyvex.com> wrote:
 I may have discovered the problem.

 ParseBlock __far inpb_block, outpb_block;

 declares one of the structs as far, the other near.  This was a mistake.

 Mark


May 16 2001
next sibling parent Mark Evans <mevans zyvex.com> writes:
Walter,

I've tried both actually, and both fail.

This is very mysterious to me why a deref assignment works and the runtime
calls don't.

Mark


On Wed, 16 May 2001 17:29:59 -0700, "Walter" <walter digitalmars.com> wrote:
 It all depends on your memory model. I'd use _fmemcpy() if in a near data
 model, and memcpy() in a far data model.
 
 
 "Mark Evans" <mevans zyvex.com> wrote in message
 news:1106_990055289 evans...
 Still I would like to understand why the assignment *outpb = *inpb works

doctor-recommended method for copying between
 near and far data segments.  And how would I assign two far objects to the

 I tried chaning both to __far and some other code broke mysteriously.  Oh

 Mark



 On Wed, 16 May 2001 21:26:39 GMT, Mark Evans <mevans zyvex.com> wrote:
 I may have discovered the problem.

 ParseBlock __far inpb_block, outpb_block;

 declares one of the structs as far, the other near.  This was a mistake.

 Mark



May 16 2001
prev sibling parent reply Mark Evans <mevans zyvex.com> writes:
Walter,

I still suspect something is wrong with putting structures inside a union.
Referring to the previous post, this failure is interesting:


SPM_APPROACH_PARAMS __far * src;
SPM_APPROACH_PARAMS __far * dest;

src = &((inpb->structs).pb_SPM_APPROACH_PARAMS);
dest = &((outpb->structs).pb_SPM_APPROACH_PARAMS);

*dest = *src; // fails


/*Approach Params from a header file*/
    typedef struct
    {
        BOOL bQuery;
        BOOL bLift;
        BOOL bAutoLift;
        BOOL bScannerXY;
        BOOL bReNull;
        BOOL bApproach;
        BOOL bSanityChecks;
        long nRetry;
        BOOL bSelectStyle;
        BOOL bCrash;
        BOOL bSelectMotor;
        BOOL bFineMotor;
        long nZMotorOptions;
        float fLiftMicrons;
        float fRetryMicrons;
        float fLiftSpeed;
        float fCrashSpeed;
        BOOL bOvershootMicrons;
        float fOvershootMicrons;
        BOOL bScannerZThreshold;
        float fScannerZThreshold;
        short nScannerZUnit;
        float fTimeoutSeconds;
        float fScannerMicronsX;
        float fScannerMicronsY;
        BOOL bESigCal;
        float fESigCalFactor;
    } SPM_APPROACH_PARAMS;
May 16 2001
parent reply "Walter" <walter digitalmars.com> writes:
Are you using C or C++? It makes a difference.

"Mark Evans" <mevans zyvex.com> wrote in message
news:1108_990060635 evans...
 Walter,

 I still suspect something is wrong with putting structures inside a union.
 Referring to the previous post, this failure is interesting:


 SPM_APPROACH_PARAMS __far * src;
 SPM_APPROACH_PARAMS __far * dest;

 src = &((inpb->structs).pb_SPM_APPROACH_PARAMS);
 dest = &((outpb->structs).pb_SPM_APPROACH_PARAMS);

 *dest = *src; // fails


 /*Approach Params from a header file*/
     typedef struct
     {
         BOOL bQuery;
         BOOL bLift;
         BOOL bAutoLift;
         BOOL bScannerXY;
         BOOL bReNull;
         BOOL bApproach;
         BOOL bSanityChecks;
         long nRetry;
         BOOL bSelectStyle;
         BOOL bCrash;
         BOOL bSelectMotor;
         BOOL bFineMotor;
         long nZMotorOptions;
         float fLiftMicrons;
         float fRetryMicrons;
         float fLiftSpeed;
         float fCrashSpeed;
         BOOL bOvershootMicrons;
         float fOvershootMicrons;
         BOOL bScannerZThreshold;
         float fScannerZThreshold;
         short nScannerZUnit;
         float fTimeoutSeconds;
         float fScannerMicronsX;
         float fScannerMicronsY;
         BOOL bESigCal;
         float fESigCalFactor;
     } SPM_APPROACH_PARAMS;

May 16 2001
next sibling parent Mark Evans <mevans zyvex.com> writes:
Plain vanilla C with no trace of C++.  My build flags are

SCFLAGS = -D_WINIO=1 -D_parkplug -mluw -Jm -p -r -WA -S -5 -a2
-IC:\DigMars\dm\include\;C:\DigMars\dm\include\win16;..\Snippets 

and all files end in .c or .h.

The syntax below is legitimate C that should work.  All I can figure is that
some kind of segmentation issue is interfering with this simple memory copy.

Mark


On Wed, 16 May 2001 19:07:40 -0700, "Walter" <walter digitalmars.com> wrote:
 Are you using C or C++? It makes a difference.
 
 "Mark Evans" <mevans zyvex.com> wrote in message
 news:1108_990060635 evans...
 Walter,

 I still suspect something is wrong with putting structures inside a union.
 Referring to the previous post, this failure is interesting:


 SPM_APPROACH_PARAMS __far * src;
 SPM_APPROACH_PARAMS __far * dest;

 src = &((inpb->structs).pb_SPM_APPROACH_PARAMS);
 dest = &((outpb->structs).pb_SPM_APPROACH_PARAMS);

 *dest = *src; // fails


 /*Approach Params from a header file*/
     typedef struct
     {
         BOOL bQuery;
         BOOL bLift;
         BOOL bAutoLift;
         BOOL bScannerXY;
         BOOL bReNull;
         BOOL bApproach;
         BOOL bSanityChecks;
         long nRetry;
         BOOL bSelectStyle;
         BOOL bCrash;
         BOOL bSelectMotor;
         BOOL bFineMotor;
         long nZMotorOptions;
         float fLiftMicrons;
         float fRetryMicrons;
         float fLiftSpeed;
         float fCrashSpeed;
         BOOL bOvershootMicrons;
         float fOvershootMicrons;
         BOOL bScannerZThreshold;
         float fScannerZThreshold;
         short nScannerZUnit;
         float fTimeoutSeconds;
         float fScannerMicronsX;
         float fScannerMicronsY;
         BOOL bESigCal;
         float fESigCalFactor;
     } SPM_APPROACH_PARAMS;


May 17 2001
prev sibling parent reply Mark Evans <mevans zyvex.com> writes:
Walter,

Think I found my bug.  I did a simple test to validate memory copying with *
and it works.

I had been assuming correct operation of another module which was incomplete
and because of that, not referencing the actual data copied.

Mark
May 17 2001
parent "Walter" <walter digitalmars.com> writes:
I'm glad you found the problem and are able to proceed. -Walter


"Mark Evans" <mevans zyvex.com> wrote in message
news:1104_990119091 evans...
 Walter,

 Think I found my bug.  I did a simple test to validate memory copying with

 I had been assuming correct operation of another module which was

 Mark

May 17 2001