Pointers 作为程序引用传递的变量的值超过其长度时发生更改的最可能原因是什么?

Pointers 作为程序引用传递的变量的值超过其长度时发生更改的最可能原因是什么?,pointers,ibm-midrange,rpgle,Pointers,Ibm Midrange,Rpgle,我的同事昨天带着一个问题来找我 他有一个定义了两个变量的CL,每个变量10个字符。然后,他用第一个变量作为参数调用另一个CL,在CL返回后(这是一个很长的程序字符串,可能需要手动梳理出有问题的代码),他的第一个变量保持不变,但第二个变量的前5个字符被消隐 因为参数是通过引用传递的,所以很明显有些东西会影响分配的10个字节以上,并且会溢出到内存中紧接着定义的变量中,但我想知道这种情况的常见示例是什么(这不会导致某种显式错误)。另一个将此地址传递给它的程序,其参数定义为15字节?使用指向地址的指针,

我的同事昨天带着一个问题来找我

他有一个定义了两个变量的CL,每个变量10个字符。然后,他用第一个变量作为参数调用另一个CL,在CL返回后(这是一个很长的程序字符串,可能需要手动梳理出有问题的代码),他的第一个变量保持不变,但第二个变量的前5个字符被消隐

因为参数是通过引用传递的,所以很明显有些东西会影响分配的10个字节以上,并且会溢出到内存中紧接着定义的变量中,但我想知道这种情况的常见示例是什么(这不会导致某种显式错误)。另一个将此地址传递给它的程序,其参数定义为15字节?使用指向地址的指针,然后取消引用并分配15个字符的字符串?这是V7R1


同时,他在这两个变量之间插入了另一个变量作为缓冲lol。有趣的是,没有赋值的变量永远不会初始化,因此它们在内存中没有任何空间。玩这个游戏时要发现一件有趣的事情。

需要做的就是调用堆栈中较低的程序错误地定义了一个参数

调用程序

/*pgm a*/
pgm
  dcl &parm1 char(10) value('Hello')
  dcl &parm2 char(10) value('Charles')

  call pgmb parm(&parm1 &parm2)
endpgm
调用程序

/*pgm b*/
pgm parm(&parmA &parmB)
  dcl &parmA char(15)
  dcl &parmB char(10)

  chgvar &parmA value('Bye')
endpgm
注意:它不一定会损坏,它可能会正常工作,直到应用了某些更改操作系统内部或编译器的PTF

我个人看到,RPG III程序多年来一直运行“良好”,但由于编译器内存布局的不同,转换为RPGIV时出现故障。RPG III程序正在损坏未使用的内存,但在RPGIV,损坏的内存非常重要


总之,如果抛出了错误,算你自己幸运吧……向下跟踪调用堆栈以找到不匹配的地方。

所有需要做的就是调用堆栈中较低的程序错误定义了一个参数

调用程序

/*pgm a*/
pgm
  dcl &parm1 char(10) value('Hello')
  dcl &parm2 char(10) value('Charles')

  call pgmb parm(&parm1 &parm2)
endpgm
调用程序

/*pgm b*/
pgm parm(&parmA &parmB)
  dcl &parmA char(15)
  dcl &parmB char(10)

  chgvar &parmA value('Bye')
endpgm
注意:它不一定会损坏,它可能会正常工作,直到应用了某些更改操作系统内部或编译器的PTF

我个人看到,RPG III程序多年来一直运行“良好”,但由于编译器内存布局的不同,转换为RPGIV时出现故障。RPG III程序正在损坏未使用的内存,但在RPGIV,损坏的内存非常重要


总之,如果抛出错误,算你自己运气好……通过调用堆栈查找不匹配项。

在两个变量之间定义另一个变量不一定会有区别。无法保证变量在存储器中的排列顺序与程序中定义的顺序相同

为了确保变量后面有额外的存储,必须明确定义额外的存储

在CL中,这样做。这将在&MYVAR之后添加保证的额外90字节

dcl &myvar_stg type(*char) len(100)                                 
   dcl &myvar type(*char) stg(*defined) len(10) defvar(&myvar_stg 1)

在这两个变量之间定义另一个变量不一定会有区别。无法保证变量在存储器中的排列顺序与程序中定义的顺序相同

为了确保变量后面有额外的存储,必须明确定义额外的存储

在CL中,这样做。这将在&MYVAR之后添加保证的额外90字节

dcl &myvar_stg type(*char) len(100)                                 
   dcl &myvar type(*char) stg(*defined) len(10) defvar(&myvar_stg 1)

假设所有涉及的程序都是可调试的,您可以通过在debug中的第二个变量上放置一个手表来准确地找出存储损坏的位置

在调试器中,使用“watch”命令,然后让程序运行

===> watch &myvar2

您将在更改存储的语句之后的下一个可调试语句上获得一个监视断点。通常,下一个可调试语句位于更改存储的同一程序中。

假设所有涉及的程序都可调试,您可以通过在debug中的第二个变量上加上一个手表来查明存储损坏的确切位置

在调试器中,使用“watch”命令,然后让程序运行

===> watch &myvar2

您将在更改存储的语句之后的下一个可调试语句上获得一个监视断点。通常,下一个可调试语句位于更改存储的同一程序中。

如果将10个字符的CL字段传递给另一个程序中的15个字符的字段(我理解正确吗?),则可以很容易地看到它将如何被截断为5个字符。了解接收节目的语言会有帮助。在RPG和COBOL中,移动值通常从右向左(即“1234567890”将变为“1234567890”,然后变为“1234567890”。应该可以将CL置于调试中,观察/监控变量,以隔离值的更改位置。可能会混淆参数应如何使用。还有另一个问题也有类似的混淆。可能下游程序只是在铺设“工作”的数据结构在第一个参数上,正在尝试维护两个参数!这不是一个好方法。最有可能的是某些程序更改了变量。这就是程序所做的。如果要保存编程保险…如果将10个字符的CL字段传递给另一个程序中的15个字符的字段(我理解正确吗?)然后可以很容易地看到它将如何被截断5个字符。这将有助于了解接收程序的语言。在RPG和COBOL中,移动值通常从右向左出现(即“1234567890”将变为“1234567890”,然后变为“1234567890”。应该可以将CL置于调试中,观察/监视变量,以隔离值的更改位置。可能会混淆参数如何更改