|
D JOBI0600 DS 322 D @@GRPPRF 137 146 D QUsrParmL S 4B 0 inz(322)
The problem here isn't that they added more data to the API, it's that you defined a parameter as a BINARY(2) when the API expects BINARY(4).
In RPG, when you're defining a variable, you define the number of digits that it needs to store. For example, a packed variable that's defined as "7P 0" occupies only 4 bytes of memory, but it stores numbers up to 7 digits long. Similarly, a "4B 0" variable stores up to 4 digits, but only occupies 2 bytes of memory.
The API documentation, however, references how many bytes it occupies. So BINARY(2) is 2 bytes of memory, or "5I 0" in RPG. BINARY(4) is 4 bytes of memory, which would be "10I 0". You could also code "4B 0" for 2 bytes or "9B 0" for 4 bytes, but you should never use the B data type in RPG unless you need to be V3R1 compatible.
The B data type is crippled. It converts everything to packed whenever you use it, which makes it slower, and also means that it's limits are defined in decimal digits instead of binary digits. A true binary type is much faster, and isn't confined by decimal digits. In RPG, data type I and U are true binary types. Use them instead.
I know it's not really pretty, but I didn't spend a lot of time thinking about a better way to define only the one subfield at the time. When we upgraded to V5R3, some weird things started happening in a couple of programs that used my code. It was fairly minor so we didn't get to it right away and the connection with the upgrade was not realized, but after a fair amount of debugging I found out that the API return DS had changed. To be honest I'm still a bit confused as to why it caused an error,
It's not because of the extra fields added to the format. They have no impact on you, as long as you define the length correctly.
Parameters work by sharing memory. Let's look at your definition again: D QUsrParmL S 4B 0 inz(322)When you define this, and the program runs, it asks the operating system for a spot in memory to store it's variable. It says "hey operating system! Yeah, you! I need 2 bytes of memory to store data in." The operating system says "Okay, dude, relax you can store your data at location 3014" (or some valid memory location)
It does the same thing with the data structure. "Operating System, I need 322 bytes of memory!" "Okay, Mr. RPG program, you can have memory at position 4292." Since you asked for 322 bytes, you have from position 4192 to 4513 of memory for your data structure.
Great. RPG then sets the memory at position 3014 to x'0142' (which is 322 in hex). It then calls the API and says "The Length parm is at position 3014."
The API, who's expecting 4 bytes of memory, reads x'01420000' from position 3014. Why isn't it just x'0142'? Because it's expecting FOUR bytes, not TWO. So it reads 2 extra bytes. In this example, I made those two extra bytes be x'0000' (but they don't have to be -- it entirely depends on what happens to be the next thing in memory after your QUsrParmL variable.)
The API says WOW! 21,102,592 bytes of memory! (x'01420000' when converted to decimal is 21102592). Heck, I can do whatever I want, I have LOADS of space!
The API was also told that JOBI0600 was at position 4192 in memory. And you've told it that it has 21mb of space at that location. So, while the operating system reserved positions 4192 - 4513 for you to use, the API is free to write from 4192 - 21106783 because you passed the length wrong. This causes the API to overwrite memory and corrupt things.
What does it overwrite? What does it corrupt? Who knows. It's whatever happens to be after your data structure in memory. It could be memory that's not currently being used. It could be other variables in your program. Or even in another program. Or even memory in use by the operating system. And the API just overwrote it because you told it the variable was longer than it really was.
This problem isn't even really related to APIs. It happened to be an API you were calling THIS time, but next time it might just be another program you wrote. You must always be careful to make sure the parameters you provide match what the program is expecting. If you pass shorter variables, you'll risk memory corruption.
where qUsrParmL is the length of the receiver variable. My assumption was that the API would only return 322 bytes given in that it was being told that was how much room was available to it.
That's exactly what the API does. But you have to pass the length correctly.
I think that when we upgraded, the API was returning a longer DS, so some other internal program memory was being corrupted. Later on in the execution we would get pointer errors. I suppose that none of the methods discussed thus far would really solve this problem, as it seems to be an API bug.
No, it's a bug in your code. You have the right idea, you just defined the variable wrong.
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.