我必须编写一段代码来进行外部合并排序。这部分是第1阶段,它用400KB排序的文件写入{num_blocos}文件:
char file_name[20];
while (1)
{
size_read = fread(bloco, tam, mem_bloco, file);
if (size_read != 0)
{
heapSort(bloco, size_read);
sprintf(file_name, "file%drun0.bin", num_blocos);
temp = fopen(file_name, "wb");
fwrite(bloco, tam, size_read, temp);
num_blocos++;
fclose(temp);
}
else
{
break;
}
}
这是第二阶段,它每次运行都合并所有文件{n乘n},或者将其重写到下一次运行。
int k = 0, n = 1, j = 0;;
char file_write[20], file_read[20];
while (n < num_blocos)
{
while (k<num_blocos)
{
sprintf(file_write, "file%drun%d.bin", k, n);
file = fopen(file_write, "wb");
if (k + 1 == num_blocos)
{
sprintf(file_read, "file%drun%d.bin", k, j);
temp = fopen(file_read, "rb");
int size = fread(bloco, tam, mem_bloco, temp);
fwrite(bloco, tam, size, file);
break;
}
else
{
mergeSortFile(k, k + n, file, j);
sprintf(file_name, "file%drun%d.bin", k, j);
remove(file_name);
sprintf(file_name, "file%drun%d.bin", k+n, j);
remove(file_name);
k += 2 * n;
}
}
k = 0;
j = n;
n *= 2;
fclose(temp);
fclose(file);
remove(file_read);
}
我的问题来了:
FILE *tempa, *tempb;
char file_name[20];
sprintf(file_name, "file%drun%d.bin", posb1, j);
tempa = fopen(file_name, "wb+");
if( tempa == NULL ) {
fprintf(stderr, "Couldn't open %s: %sn", file_name, strerror(errno));
exit(1);
}
sprintf(file_name, "file%drun%d.bin", posb2, j);
tempb = fopen(file_name, "wb+");
if( tempb == NULL ) {
fprintf(stderr, "Couldn't open %s: %sn", file_name, strerror(errno));
exit(1);
}
当我的原始文件有1MB时,它工作得很好,但当它有99MB时,这是我想要的大小,甚至是6MB,它给了我分段错误,在调试之后,我发现它是在tempb fopen试图打开文件时";file10run1.bin";在6 MB或更多MB中,有人可以给我一盏灯吗?
您在同一个temp
文件句柄上多次使用fclose
。
使用Address Sanitizer运行测试程序的收益率:
=================================================================
==3720049==ERROR: AddressSanitizer: attempting double-free on 0x615000002100 in thread T0:
#0 0x7f51a7ee4277 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x107277)
#1 0x7f51a7c8dd5f in _IO_deallocate_file /build/glibc-M65Gwz/glibc-2.30/libio/libioP.h:863
#2 0x7f51a7c8dd5f in _IO_new_fclose /build/glibc-M65Gwz/glibc-2.30/libio/iofclose.c:74
#3 0x7f51a7ee2490 in __interceptor_fclose (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x105490)
#4 0x5615b5ab1805 in fileSort /tmp/so/extsort.c:106
#5 0x5615b5ab131c in main /tmp/so/extsort.c:27
#6 0x7f51a7c40e0a in __libc_start_main ../csu/libc-start.c:308
#7 0x5615b5ab1249 in _start (/tmp/so/a.out+0x1249)
0x615000002100 is located 0 bytes inside of 488-byte region [0x615000002100,0x6150000022e8)
freed by thread T0 here:
#0 0x7f51a7ee4277 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x107277)
#1 0x7f51a7c8dd5f in _IO_deallocate_file /build/glibc-M65Gwz/glibc-2.30/libio/libioP.h:863
#2 0x7f51a7c8dd5f in _IO_new_fclose /build/glibc-M65Gwz/glibc-2.30/libio/iofclose.c:74
previously allocated by thread T0 here:
#0 0x7f51a7ee4628 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x107628)
#1 0x7f51a7c8e62a in __fopen_internal /build/glibc-M65Gwz/glibc-2.30/libio/iofopen.c:65
#2 0x6e69622e306e74 (<unknown module>)
SUMMARY: AddressSanitizer: double-free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x107277) in __interceptor_free
==3720049==ABORTING
下面的补丁修复了这个问题,但其他地方还有两个内存泄漏(剩下的只是一个微不足道的练习,需要您修复,请使用gcc -fsanitize=address
查找(:
--- extsort.c 2020-07-19 17:42:02.354991453 -0700
+++ extsort-fixed.c 2020-07-19 17:41:57.067008342 -0700
@@ -64,6 +64,7 @@
fwrite(bloco, size, size_read, temp);
num_blocos++;
fclose(temp);
+ temp = NULL;
}
else
{
@@ -103,7 +104,10 @@
k = 0;
j = n;
n *= 2;
- fclose(temp);
+ if (temp != NULL)
+ fclose(temp);
+ temp = NULL;
+
fclose(file);
remove(file_read);
}