I'm working on very old legacy code and I'm porting it from 32 to 64 bit.
One of the things where I'm struggling was about the MFC serialization. One of the difference between 32 and 64 bit was the size of pointer data. This means, for example, that if for some reason I have serialized the size of a CArray like
ar << m_array.GetSize();
the data was different between 32 and 64 platform because GetSize return a INT_PTR
. To get serialize data fully compatible with the same application compiled in 32 and 64 bit, I forced the data type in the storing phase, and the same on reading. (pretty sure 32 bit are enough for this data)
store
ar << (int)m_array.GetSize();
reading
int iNumSize = 0;
ar >> iNumSize ;
In other word, the application, does't matter if compiled in 32 or 64 bits, serialize this data like as int
.
Now I have one doubt about the serialization of the CArray type; to serialize a CArray the code use the built CArchive serialization
//defined as CArray m_arrayVertex; on .h
m_arrayVertex.Serialize(ar);
and this Serialize is defined in the MFC file afxtemp.h with this template
template<class TYPE, class ARG_TYPE>
void CArray<TYPE, ARG_TYPE>::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
CObject::Serialize(ar);
if (ar.IsStoring())
{
ar.WriteCount(m_nSize);
}
else
{
DWORD_PTR nOldSize = ar.ReadCount();
SetSize(nOldSize, -1);
}
SerializeElements<TYPE>(ar, m_pData, m_nSize);
}
where (afx.h)
// special functions for reading and writing (16-bit compatible) counts
DWORD_PTR ReadCount();
void WriteCount(DWORD_PTR dwCount);
Here my question: ReadCount and WriteCount use the DWORD_PTR
that have different size between platforms... this kind of serilization is compatible at 32/64 bit or, due to the size change, the serialized data work only in each platfrom respectively?
I mean the data can be read by both the 32 and 64 application without errors? the comment say it works also for "16 bit" and I not found anything in details about this serialization.
If this does't work, there is a workaround to serialize the CArray in such a way the data are fully compatible with both 32 and 64 app?
CodePudding user response:
Storage and retrieval of the item count for CArray
instantiations are implemented in CArchive::WriteCount
and CArchive::ReadCount
, respectively.
They write and read a 16-bit (WORD
), 32-bit (DWORD
), or 64-bit (on 64-bit platforms, DWORD_PTR
) value to or from the stream. Writing uses the following algorithm:
- If the item count is less than
0xFFFF
, write the item count as a 16-bitWORD
value - Otherwise, dump an "invalid value" marker (
(WORD)0xFFFF
) into the stream, followed by- 32-bit: The item count as a 32-bit value (
DWORD
) - 64-bit: If the item count is less than
0xFFFF'FFFF
, write the item count as a 32-bitDWORD
value- Otherwise, dump an "invalid value" marker (
(DWORD)0xFFFFFFFF
) inthe to the stream, followed by the item count as a 64-bit value (DWORD_PTR
)
- Otherwise, dump an "invalid value" marker (
- 32-bit: The item count as a 32-bit value (
When deserializing the stream the code reads the item count value, checks to see if it matches the "invalid value" marker, and continues with larger values if a marker was found.
This works across bitnesses as long as the CArray
holds no more than 0xFFFF'FFFE
values. For 32-bit platforms this is always true; you cannot have a CArray
that uses up the entire address space.
When serializing from a 64-bit process you just need to make sure that there aren't any more than 0xFFFF'FFFE
items in the array.
CodePudding user response:
As you have written, ReadCount
returns a DWORD_PTR
which is either 32 bit or 64 bits wide depending if the code has been compliled as 32 or 64 bit code.
Now as long as the actual object count fits into 32 bits, there is no problem with interoperability between files that have been written by a 32 bit or a 64 bit program.
On the other hand if your 64 bit code serializes a CArray that has more than 4294967295 elements (which is unlikely to happen anyway), then you will run into trouble if you want to read deserialze this file from a 32 bit program. But on a 32 bit program a CArray cannot store more than 4294967295 anyway.
Long story short meaning, you don't need to do anything special, just serialize/deserialze your data.