Archives
D Programming
DD.gnu digitalmars.D digitalmars.D.bugs digitalmars.D.dtl digitalmars.D.dwt digitalmars.D.announce digitalmars.D.learn digitalmars.D.debugger C/C++ Programming
c++c++.announce c++.atl c++.beta c++.chat c++.command-line c++.dos c++.dos.16-bits c++.dos.32-bits c++.idde c++.mfc c++.rtl c++.stl c++.stl.hp c++.stl.port c++.stl.sgi c++.stlsoft c++.windows c++.windows.16-bits c++.windows.32-bits c++.wxwindows digitalmars.empire digitalmars.DMDScript |
c++ - Union bug??
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
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
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
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 May 16 2001
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 May 16 2001
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
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
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
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
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 May 17 2001
|