GNU COBOL实现的Quick Sort返回无效结果问题排查
GNU COBOL 3.2.2 递归快速排序异常问题排查
问题描述
我基于标准快速排序逻辑,在GNU COBOL 3.2.2中用递归子程序实现排序,这套逻辑在C、Python等语言中运行正常,但在COBOL中执行后,数组排序结果常出现无效值。数组已被完全填充有效数据,递归逻辑看起来无明显错误,怀疑问题源于GNU COBOL对以下特性的特殊处理:
- 递归子程序调用机制
- 数组按引用传递方式
DEPENDING ON动态数组的处理- 运行时内存布局
完整代码示例
主程序 quick_sort.cbl
IDENTIFICATION DIVISION. PROGRAM-ID. QUICK-SORT-MAIN. DATA DIVISION. WORKING-STORAGE SECTION. 01 ARRAY-SIZE PIC 9(4) VALUE 1000. 01 UNSORTED-ARRAY. 05 ARRAY-ELEMENT PIC 9(4) OCCURS 1 TO 9999 DEPENDING ON ARRAY-SIZE. 01 START-TIME PIC 9(18). 01 END-TIME PIC 9(18). 01 ELAPSED-TIME PIC 9(18). PROCEDURE DIVISION. CALL "GETMICROSEC" USING START-TIME. * 填充数组逻辑(确保数组已完全填充有效数据) CALL "QUICK-SORT-SUB" USING UNSORTED-ARRAY, 1, ARRAY-SIZE. CALL "GETMICROSEC" USING END-TIME. COMPUTE ELAPSED-TIME = END-TIME - START-TIME. DISPLAY "排序完成,耗时:" ELAPSED-TIME "微秒". STOP RUN.
递归子程序 quick_sort_sub.cbl
IDENTIFICATION DIVISION. PROGRAM-ID. QUICK-SORT-SUB RECURSIVE. DATA DIVISION. LINKAGE SECTION. 01 SORT-ARRAY. 05 ARRAY-ELEMENT PIC 9(4) OCCURS 1 TO 9999 DEPENDING ON ARRAY-SIZE. 01 LOW PIC 9(4). 01 HIGH PIC 9(4). 01 ARRAY-SIZE PIC 9(4). WORKING-STORAGE SECTION. 01 I PIC 9(4). 01 J PIC 9(4). 01 PIVOT PIC 9(4). 01 TEMP PIC 9(4). PROCEDURE DIVISION USING SORT-ARRAY, LOW, HIGH. IF LOW >= HIGH EXIT PROGRAM. MOVE LOW TO I. MOVE HIGH TO J. MOVE ARRAY-ELEMENT(I) TO PIVOT. PERFORM UNTIL I >= J PERFORM UNTIL ARRAY-ELEMENT(I) > PIVOT OR I >= HIGH ADD 1 TO I END-PERFORM. PERFORM UNTIL ARRAY-ELEMENT(J) < PIVOT OR J <= LOW SUBTRACT 1 FROM J END-PERFORM. IF I < J MOVE ARRAY-ELEMENT(I) TO TEMP MOVE ARRAY-ELEMENT(J) TO ARRAY-ELEMENT(I) MOVE TEMP TO ARRAY-ELEMENT(J) END-PERFORM. MOVE ARRAY-ELEMENT(J) TO ARRAY-ELEMENT(LOW) MOVE PIVOT TO ARRAY-ELEMENT(J). CALL "QUICK-SORT-SUB" USING SORT-ARRAY, LOW, J - 1. CALL "QUICK-SORT-SUB" USING SORT-ARRAY, J + 1, HIGH. EXIT PROGRAM.
计时函数 getmicrosec.cpp
#include <sys/time.h> extern "C" void getmicrosec(long long *time) { struct timeval tv; gettimeofday(&tv, NULL); *time = (long long)tv.tv_sec * 1000000 + tv.tv_usec; }
编译命令
# 编译C计时函数 g++ -c getmicrosec.cpp -o getmicrosec.o # 编译COBOL子程序 cobc -c quick_sort_sub.cbl -o quick_sort_sub.o # 编译主程序并链接 cobc quick_sort.cbl quick_sort_sub.o getmicrosec.o -o quick_sort -x
问题排查与解决方向
- 动态数组大小未传递:递归子程序的
LINKAGE SECTION中,ARRAY-SIZE是动态数组的依赖变量,但主程序调用时未传递该值,导致子程序无法确定数组实际有效长度,访问时易触发内存越界。解决方法:在主程序调用时添加ARRAY-SIZE作为参数,确保子程序能正确获取数组边界。 - 递归栈溢出:当数组规模较大时,GNU COBOL默认递归栈大小可能不足以支撑多层调用,引发栈溢出破坏数据。可通过编译选项
-fstack-size=4096(根据实际需求调整数值)增大栈空间。 - 数组索引越界:COBOL数组索引从1开始,递归调用时
J-1可能得到0,导致下一层调用索引非法;循环中I >= HIGH的判断逻辑存在漏洞,可能导致访问超出数组有效范围。需在递归调用前检查LOW < J-1再执行,同时调整循环终止条件确保索引始终在1到数组大小之间。 - 添加调试输出:在 pivot 选择、元素交换、递归前后等关键步骤添加
DISPLAY语句,输出当前I、J、PIVOT及对应位置的数组元素值,定位数据异常的触发时机,排查具体逻辑错误。
内容的提问来源于stack exchange,提问作者TranTrung
相关产品推荐
相关产品推荐

