|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
 |
|
MQRFH.StrucId contains superfluous SOH character (ASCII 01) |
« View previous topic :: View next topic » |
Author |
Message
|
Pootle |
Posted: Thu Dec 18, 2014 8:20 am Post subject: MQRFH.StrucId contains superfluous SOH character (ASCII 01) |
|
|
Newbie
Joined: 18 Dec 2014 Posts: 7
|
I am currently working on a project migrating from Solaris to Linux. Following a problem encountered, I wrote a small test program as below, with the output shown on Solaris and Linux. As seen, on Linux despite being an MQCHAR4 field the StrucId has an additional SOH character at the end. I'm at a loss as to why this should be so any input is welcome!
MQRFH m_rfh = {MQRFH_DEFAULT};
cout << "MQRFH.StrucId is of length " << strlen(m_rfh.StrucId) << " bytes" << endl;
cout << "Contents of MQRFH.StrucId: " << endl;
for (int i=0; i<strlen(m_rfh.StrucId); i++)
{
printf("%02X\n", m_rfh.StrucId[i]);
}
Output on Linux:
MQRFH.StrucId is of length 5 bytes
Contents of MQRFH.StrucId:
52
46
48
20
01
Output on Solaris:
MQRFH.StrucId is of length 4 bytes
Contents of MQRFH.StrucId:
52
46
48
20 |
|
Back to top |
|
 |
PaulClarke |
Posted: Thu Dec 18, 2014 8:50 am Post subject: |
|
|
 Grand Master
Joined: 17 Nov 2005 Posts: 1002 Location: New Zealand
|
I think it is your program that is at fault.
The StrucId is character data but it is not NULL terminated, it is a fixed size of 4 bytes. Your program is using strlen() to calculate the length of the string which is incorrect. You are at themercy of what comes next in the structure. As it happens what comes next is a Version. So, on Big endian machines you will see a 0 in the next position. However, on little endian machines the version number 1 will be in the next byte.
Cheers,
Paul. _________________ Paul Clarke
MQGem Software
www.mqgem.com |
|
Back to top |
|
 |
Pootle |
Posted: Fri Dec 19, 2014 11:15 am Post subject: |
|
|
Newbie
Joined: 18 Dec 2014 Posts: 7
|
Many thanks for your quick reply Paul. Having taken the time to understand endian-ness and looked further at our application I think it is the code below which is causing our problem. I presume that on little endian when m_rfh.StrucId is copied into buf it includes the little end byte from the version number and then is terminated by the next byte of version number as it is null. Whereas on big endian the big end byte of the version number is null so serves to terminate immediately.
Could you please confirm my understanding?
sprintf
( buf, "%-4s%012ld%012ld%012d%012ld%-8s%012ld"
, m_rfh.StrucId
, (long)m_rfh.Version
, (long)length()
, m_rfh.Encoding
, (long)m_rfh.CodedCharSetId
, m_rfh.Format
, (long)m_rfh.Flags
);
return string(buf); |
|
Back to top |
|
 |
PaulClarke |
Posted: Fri Dec 19, 2014 12:05 pm Post subject: |
|
|
 Grand Master
Joined: 17 Nov 2005 Posts: 1002 Location: New Zealand
|
Yes, that is correct. Your code could be fixed by changing it to....
Code: |
sprintf
( buf, "%-4.4s%012ld%012ld%012d%012ld%-8.8s%012ld"
, m_rfh.StrucId
, (long)m_rfh.Version
, (long)length()
, m_rfh.Encoding
, (long)m_rfh.CodedCharSetId
, m_rfh.Format
, (long)m_rfh.Flags
);
return string(buf);
|
Cheers,
Paul. _________________ Paul Clarke
MQGem Software
www.mqgem.com |
|
Back to top |
|
 |
tczielke |
Posted: Fri Dec 19, 2014 12:16 pm Post subject: |
|
|
Guardian
Joined: 08 Jul 2010 Posts: 941 Location: Illinois, USA
|
The problem is with the first snippet of code that you posted, and its use of strlen, as Paul mentioned. If this is C, I would use something like sizeof(m_rfh.StrucId), instead of strlen(m_rfh.StrucId) to calculate the size of the StrucId.
Here is why your code is probably currently not working. More than likely, your Solaris is Solaris SPARC (Sparc is a big-endian processor) and your Linux is Linux x86 (x86 is a little endian processor).
On a big-endian SPARC processor, the first 8 bytes of the MQRFH structure would lay out in memory as follows (we will assume it starts at address x'1000')
Address Value
x'1000' = x'52' or R
x'1001' = x'46' or F
x'1002' = x'48' or H
x'1003' = x'20' or Space
x'1004' = x'00'
x'1005 = x'00'
x'1006' = x'00'
x'1008' = x'01'
On a little-endian x86 processor, the first 8 bytes of the MQRFH structure would lay out in memory as follows (we will assume it starts at address x'1000')
Address Value
x'1000' = x'52' or R
x'1001' = x'46' or F
x'1002' = x'48' or H
x'1003' = x'20' or Space
x'1004' = x'01'
x'1005 = x'00'
x'1006' = x'00'
x'1008' = x'00'
When you use strlen(m_rfh.StrucId), you are saying pass in the address of where m_rfh.StrucId starts (which would be x'1000' in our example), and traverse from that address until you encounter a x'00'. For the big-endian case, that is address x'1004' which returns a strlen of 4. For the little-endian case, that is address x'1005' which returns a strlen of 5. |
|
Back to top |
|
 |
Pootle |
Posted: Sat Dec 20, 2014 8:36 am Post subject: |
|
|
Newbie
Joined: 18 Dec 2014 Posts: 7
|
Thanks both. You've made it very clear to me. |
|
Back to top |
|
 |
|
|
 |
|
Page 1 of 1 |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|
|