在下面的代码中,结果没问题,但是代码在执行完成时将崩溃,并增加一个错误:检测到堆损坏,空闲列表在0x600000008f50处被破坏
int *mergeSort(int *a,int count) {
int leftCount = count / 2;
int rightCount = count - leftCount;
int *leftData = getData(a, 0, leftCount);
int *rightData = getData(a, leftCount, count);
int *sortedLeftData = mergeSort(leftData, leftCount);
int *sortedRightData = mergeSort(rightData, rightCount);
int *resultData = mergeData(sortedLeftData, sortedRightData, leftCount,
rightCount);
return resultData;
}
int *getData(int *a,int from, int to) {
if (from > to) { return nil; }
int *res = malloc(to - from + 1);
for (int index = from; index < to; index ++) {
int value = a[index];
res[index-from] = value;
}
return res;
}
int *mergeData(int *a, int *b, int acount, int bcount) {
int *result = malloc(acount + bcount);
int aindex,bindex,rindex;
aindex = bindex = rindex = 0;
while (aindex < acount | bindex < bcount) {
int value,avalue = INT_MAX,bvalue = INT_MAX;
if (aindex < acount) { avalue = a[aindex]; }
if (bindex < bcount) { bvalue = b[bindex]; }
// get value from a point.
if (avalue <= bvalue) {
value = avalue;
aindex ++;
}else {
// get value from b point.
value = bvalue;
bindex ++;
}
result[rindex] = value;
rindex ++;
}
return result;
}
我不明白为什么在释放积分时会崩溃,任何答案都会有所帮助,谢谢。
答案 0 :(得分:2)
所有分配都太小,因此缓冲区溢出。
malloc
函数分配请求的 bytes 个字节。如果您的元素是sizeof(int)
类型,则需要将所需的元素数乘以int
。 例如
int *result = malloc((acount + bcount) * sizeof(int));
我在阅读代码时发现的其他潜在问题是:
使用按位或运算符代替逻辑或:
while (aindex < acount | bindex < bcount)
// ^ should be ||
您永远不会释放临时缓冲区,因此您的程序将因疯狂泄漏而耗尽内存。完成操作后,必须在leftData
函数中释放rightData
,sortedLeftData
,sortedRightData
和mergeSort
。
请注意,合并排序实际上不需要太多分配。这样做将对性能产生巨大影响。一个有效的实现只需要一个用于暂存操作的附加缓冲区,就可以在开始时分配它。
答案 1 :(得分:0)
我的实现合并排序使用单个缓冲区,如下代码:
void mergeSort(int *a, int count) {
int *tempBuffer = malloc(count * sizeof(int));
mergeSortWithBuffer(a, 0, 0, count - 1,tempBuffer);
free(tempBuffer);
}
void mergeSortWithBuffer(int *a, int leftStart, int rightStart, int end, int *tempBuffer) {
int leftCount = rightStart - leftStart;
int rightCount = end - rightStart + 1;
if (leftCount + rightCount <= 1) { return; }
if (leftCount != 0) {
// left dichotomy
int lls = leftStart;
int lrs = leftStart + leftCount/2;
int lnd = rightStart - 1;
mergeSortWithBuffer(a, lls, lrs, lnd,tempBuffer);
}
if (rightCount != 0) {
// right dichotomy
int rls = rightStart;
int rrs = rightStart + rightCount/2;
int rnd = end;
mergeSortWithBuffer(a, rls, rrs, rnd,tempBuffer);
}
mergeData(a, leftStart, rightStart, end, tempBuffer);
}
void mergeData(int *a, int leftStart, int rightStart, int end,int *tempBuffer) {
int leftCount = rightStart - leftStart;
int rightCount = end - rightStart + 1;
int lindex,rindex;
lindex = rindex = 0;
while (lindex < leftCount || rindex < rightCount) {
int lv = INT_MAX,rv = INT_MAX;
if (lindex < leftCount) { lv = a[leftStart + lindex]; }
if (rindex < rightCount) { rv = a[rightStart + rindex]; }
if (lv <= rv) {
tempBuffer[leftStart + lindex + rindex] = lv;
lindex ++;
}else {
tempBuffer[leftStart + lindex + rindex] = rv;
rindex ++;
}
}
for (int index = 0; index < end - leftStart + 1; index ++) {
a[leftStart + index] = tempBuffer[leftStart + index];
}
}
我认为mergeData函数可以在没有临时缓冲区的情况下互相替换数据,但是逻辑过于复杂且效率不高,因此我在此函数中添加了临时缓冲区。
如果愿意,您有更好的建议吗?