在对包含 100 万个元素的数组进行排序时,如何找到合并排序算法崩溃的原因?
How can I find why my merge sorting algorithm crash when sorting an array of 1 million element?
我是一名法国学生,正在尝试针对不同大小的数组计算合并排序算法的执行时间。
我还想在 .csv 文件中写入不同的执行时间。但是当我的程序试图对具有 100 万个元素的数组进行排序时,过程 returns -1073741571 (0xC00000FD)
in Code::Blocks。因此,如果您能指出找到解决方案的方法,我将不胜感激!
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void genTab(int *tab, int n) {
int i;
for (i = 0; i < n; i++) {
tab[i] = rand() % 100;
}
}
void fusion(int *tab, int deb, int mid, int fin) {
int i = deb;
int j = mid + 1;
int k = deb;
int temp[fin + 1];
while ((i <= mid) && (j <= fin)) {
if (tab[i] <= tab[j]) {
temp[k] = tab[i];
i++;
} else {
temp[k] = tab[j];
j++;
}
k++;
}
while (i <= mid) {
temp[k] = tab[i];
i++;
k++;
}
while (j <= fin) {
temp[k] = tab[j];
k++;
j++;
}
for (i = deb; i <= fin; i++) {
tab[i] = temp[i];
}
}
void triFusion(int *tab, int i, int j) {
if (i < j) {
triFusion(tab, i, (int)((i + j) / 2));
triFusion(tab, (int)((i + j) / 2 + 1), j);
fusion(tab, i, (int)((i + j) / 2), j);
}
}
void reset(int *tab1, int *tab2, int n) {
for (int i = 0; i < n; i++) {
tab2[i] = tab1[i];
}
}
int main() {
srand(time(NULL));
clock_t start, end;
int nbrTest[15] = {
1000, 5000, 10000, 50000, 80000, 100000, 120000, 140000,
150000, 180000, 200000, 250000, 300000, 450000, 1000000
};
FILE *fp;
char *tpsExecution = "exeTime.csv";
fp = fopen(tpsExecution, "w");
fprintf(fp, "Array Size; Merge Time");
for (int i = 0; i < 15; i++) {
int n = nbrTest[i];
printf("Calculating time for an array of %d \n", n);
int *tab = malloc(sizeof(int) * n);
genTab(tab, n);
int *copie = malloc(sizeof(int) * n);
reset(tab, copie, n);
start = clock();
triFusion(tab, 0, n - 1);
end = clock();
float tpsFusion = (float)(end - start) / CLOCKS_PER_SEC;
reset(tab, copie, n);
printf("writing in the file\n");
fprintf(fp, "\n%d;%f", n, tpsFusion);
free(tab);
free(copie);
}
fclose(fp);
return 0;
}
int temp[fin+1];
可能超过堆栈的 space 限制。您应该改为使用 malloc
分配它,并使用 free
.
释放它
如果要将malloc
和free
排除在定时代码之外,分配可以在定时代码之外进行,并作为工作传入space。
(注意:在@Eric Postpischil 的回答后发布)。
函数
void fusion(int * tab, int deb, int mid, int fin)
有线
int temp[fin+1];
而 fin
的值是通过另一个函数从要排序的元素数 n
中得到的
triFusion(tab, 0, n-1);
并且作为一个自动变量,当 n
很大时打破堆栈。
我建议将此行替换为
int *temp = malloc((fin+1) * sizeof *temp);
if(temp == NULL) {
puts("malloc");
exit(1);
}
// ...
free(temp);
fusion() 始终为 temp 分配整个数组大小,即使只使用了一小部分 temp。您可以将其更改为:
int k = 0;
...
int temp[fin+1-deb];
...
tab[i]=temp[i-deb];
如果 n 很大,这仍然会超出堆栈 space。因此,正如其他答案中所建议的那样:
int k = 0;
...
int *temp = malloc((fin+1-deb)*sizeof(int));
...
tab[i]=temp[i-deb];
...
free(temp)
或者更好的是,在 main 或 "helper" 函数中一次性分配第二个数组,在合并排序函数中包含指向第二个数组的指针。
我是一名法国学生,正在尝试针对不同大小的数组计算合并排序算法的执行时间。
我还想在 .csv 文件中写入不同的执行时间。但是当我的程序试图对具有 100 万个元素的数组进行排序时,过程 returns -1073741571 (0xC00000FD)
in Code::Blocks。因此,如果您能指出找到解决方案的方法,我将不胜感激!
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void genTab(int *tab, int n) {
int i;
for (i = 0; i < n; i++) {
tab[i] = rand() % 100;
}
}
void fusion(int *tab, int deb, int mid, int fin) {
int i = deb;
int j = mid + 1;
int k = deb;
int temp[fin + 1];
while ((i <= mid) && (j <= fin)) {
if (tab[i] <= tab[j]) {
temp[k] = tab[i];
i++;
} else {
temp[k] = tab[j];
j++;
}
k++;
}
while (i <= mid) {
temp[k] = tab[i];
i++;
k++;
}
while (j <= fin) {
temp[k] = tab[j];
k++;
j++;
}
for (i = deb; i <= fin; i++) {
tab[i] = temp[i];
}
}
void triFusion(int *tab, int i, int j) {
if (i < j) {
triFusion(tab, i, (int)((i + j) / 2));
triFusion(tab, (int)((i + j) / 2 + 1), j);
fusion(tab, i, (int)((i + j) / 2), j);
}
}
void reset(int *tab1, int *tab2, int n) {
for (int i = 0; i < n; i++) {
tab2[i] = tab1[i];
}
}
int main() {
srand(time(NULL));
clock_t start, end;
int nbrTest[15] = {
1000, 5000, 10000, 50000, 80000, 100000, 120000, 140000,
150000, 180000, 200000, 250000, 300000, 450000, 1000000
};
FILE *fp;
char *tpsExecution = "exeTime.csv";
fp = fopen(tpsExecution, "w");
fprintf(fp, "Array Size; Merge Time");
for (int i = 0; i < 15; i++) {
int n = nbrTest[i];
printf("Calculating time for an array of %d \n", n);
int *tab = malloc(sizeof(int) * n);
genTab(tab, n);
int *copie = malloc(sizeof(int) * n);
reset(tab, copie, n);
start = clock();
triFusion(tab, 0, n - 1);
end = clock();
float tpsFusion = (float)(end - start) / CLOCKS_PER_SEC;
reset(tab, copie, n);
printf("writing in the file\n");
fprintf(fp, "\n%d;%f", n, tpsFusion);
free(tab);
free(copie);
}
fclose(fp);
return 0;
}
int temp[fin+1];
可能超过堆栈的 space 限制。您应该改为使用 malloc
分配它,并使用 free
.
如果要将malloc
和free
排除在定时代码之外,分配可以在定时代码之外进行,并作为工作传入space。
(注意:在@Eric Postpischil 的回答后发布)。
函数
void fusion(int * tab, int deb, int mid, int fin)
有线
int temp[fin+1];
而 fin
的值是通过另一个函数从要排序的元素数 n
中得到的
triFusion(tab, 0, n-1);
并且作为一个自动变量,当 n
很大时打破堆栈。
我建议将此行替换为
int *temp = malloc((fin+1) * sizeof *temp);
if(temp == NULL) {
puts("malloc");
exit(1);
}
// ...
free(temp);
fusion() 始终为 temp 分配整个数组大小,即使只使用了一小部分 temp。您可以将其更改为:
int k = 0;
...
int temp[fin+1-deb];
...
tab[i]=temp[i-deb];
如果 n 很大,这仍然会超出堆栈 space。因此,正如其他答案中所建议的那样:
int k = 0;
...
int *temp = malloc((fin+1-deb)*sizeof(int));
...
tab[i]=temp[i-deb];
...
free(temp)
或者更好的是,在 main 或 "helper" 函数中一次性分配第二个数组,在合并排序函数中包含指向第二个数组的指针。