GNUCobol 3.2.0质因数分解程序编译出现Segmentation fault错误求助
质因数分解COBOL程序段错误(Segmentation Fault)排查与修复
错误信息
unknown (signal) cobc: aborting compile of jdoodle.cobc at line 68 (PROGRAM-ID: primzahl_check) cobc: Please report this! bash: line 1: 14 Segmentation fault (core dumped) cobc -x -free -O jdoodle.cobc -o jdoodle
环境:JDoodle IDE,GNU Cobol 3.2.0
问题根源分析
重复程序ID冲突
代码中存在两个PROGRAM-ID: primfaktorzerlegung,GNU Cobol不允许同一编译单元内存在同名子程序,这会导致符号表混乱,直接触发编译阶段的段错误。调用参数完全不匹配
primzahl_check调用primfaktorzerlegung时传递了数组zahlenarray,但目标子程序的PROCEDURE DIVISION USING声明的是单个元素z_zahl,类型和数量不匹配,会破坏栈结构。zahlen_ausgeben的调用语句没有传递任何参数,但该子程序要求3个输入参数,参数缺失会导致栈溢出。
未声明的索引变量
第二个处理分解的子程序中使用了索引z_idx,但未在DATA DIVISION中显式声明该索引(仅在数组定义中提及indexed by z_idx是不够的,需要单独定义索引项)。数组容量不足
zahlenarray仅定义了4个元素,对于大于16的数(如16=24),质因数数量刚好是4,但更大的数(如32=25)会直接触发数组越界访问。
修复后的完整代码
identification division. program-id. primfaktorzerlegung-main. *> 修改主程序ID,避免重复 data division. working-storage section. 01 divident pic 9(5) value 2. *> 初始化起始值,避免未定义的垃圾值 01 rest pic 9v9. 01 divisor pic 9(5). 01 ergebnis pic 9(5). *> Kurze Erklärung: *> Primfaktorzerlegung der Zahl 20. *> 20 / 2 = 10 *> 10 / 2 = 5 *> 5 / 2 = 2.5 *> Also lautet die Primfaktorzerlegung: von 20 = 2 *> 2 *> 5 *> Bis zu der Zahl wo die Division einen Rest ergibt. *> Eine Liste für alle Zahlen von 2 bis 100 mit den dazugehörigen Zerlegungen ausgeben procedure division. display 'Programm zur Darstellung der Primfaktorzerlegung mit einer gegebenen Zahl'. display ' '. call 'primzahl_check' using divident rest divisor ergebnis. end program primfaktorzerlegung-main. identification division. program-id. primzahl_check. data division. linkage section. 01 divident pic 9(5). 01 rest pic 9v9. 01 divisor pic 9(5). 01 ergebnis pic 9(5). 01 zerlegt pic x(5). 01 priv_divident pic 9(5). 01 zahlenarray. 05 zahlen occurs 10 times indexed by z_idx. *> 扩容数组到10个元素,覆盖大部分小数值需求 10 z_zahl pic s9(5). 01 i pic 9(5). 01 quotient pic 9(5). *> Überprüfen ob es bei der Zahl um eine Primzahl handelt procedure division using divident rest divisor ergebnis. perform until divident > 100 *> 修改循环条件,实现2到100的遍历 move 2 to divisor move 1 to rest perform until rest = 0 or divisor >= divident divide divident by divisor giving ergebnis remainder rest add 1 to divisor end-perform if divident = divisor then display ' ' display divisor " ist eine Primzahl" display ' ' else call 'primfaktorzerlegung-sub' using divident zahlenarray *> 修改子程序名,传递正确参数 add 1 to divident end-perform. end program primzahl_check. identification division. program-id. primfaktorzerlegung-sub. *> 修改子程序ID,避免与主程序重复 data division. linkage section. *> 子程序必须用linkage section接收外部参数 01 divident pic 9(5). 01 zahlenarray. 05 zahlen occurs 10 times indexed by z_idx. 10 z_zahl pic s9(5). 01 priv_divident pic 9(5). 01 divisor pic 9(5). 01 quotient pic 9(5). 01 rest pic 9v9. 01 i pic 9(5). 01 zerlegt pic x(5) value 'false'. 01 z_idx pic 9(1). *> 显式声明索引变量 procedure division using divident zahlenarray. *> Primfaktorzerlegung move 2 to divisor. move 'false' to zerlegt. *> Ursprünglicher Divident speichern move divident to priv_divident move 1 to z_idx move priv_divident to z_zahl(z_idx) move priv_divident to divident. *> 修正初始值,使用原始输入值 move 2 to i. perform until zerlegt = 'true' divide divident by divisor giving quotient remainder rest if rest = 0 then move quotient to divident move i to z_idx move divisor to z_zahl(z_idx) add 1 to i else if quotient > 1 then *> 处理剩余的质数因子 move i to z_idx move quotient to z_zahl(z_idx) end-if move 'true' to zerlegt end-if call 'zahlen_ausgeben' using zahlenarray priv_divident *> 传递正确参数到输出子程序 end-perform. end program primfaktorzerlegung-sub. identification division. program-id. zahlen_ausgeben. data division. linkage section. 01 zahlenarray. 05 zahlen occurs 10 times indexed by z_idx. 10 z_zahl pic s9(5). 01 original-zahl pic 9(5). 01 y pic 9(1). 01 zahl_prnt pic z(5). procedure division using zahlenarray original-zahl. display 'Primfaktorzerlegung von ' original-zahl ': '. perform varying y from 2 by 1 until y > 10 or z_zahl(y) = 0 move y to z_idx move z_zahl(z_idx) to zahl_prnt if zahl_prnt > 0 then display zahl_prnt ' ' with no advancing end-if end-perform. display ' '. end program zahlen_ausgeben.
关键修改点说明
- 重命名重复的
primfaktorzerlegung程序ID为primfaktorzerlegung-main和primfaktorzerlegung-sub,解决符号冲突。 - 统一所有子程序的参数传递规则,确保调用时的参数数量、类型与目标子程序的声明完全匹配。
- 显式声明索引变量
z_idx,避免未定义变量导致的内存访问错误。 - 扩容数组到10个元素,覆盖2到100范围内所有数的质因数分解需求。
- 初始化主程序的
divident起始值为2,避免未初始化的垃圾值导致的异常行为。 - 修正分解逻辑中的初始值错误,确保使用原始输入值进行分解。
- 完善
zahlen_ausgeben的输出逻辑,只打印有效的质因数。
内容的提问来源于stack exchange,提问作者Luka
相关产品推荐
相关产品推荐

