[英]I'm not sure why my code in C is giving me a segmentation fault at free, any ideas?
So this is my code which runs up till free(right);所以这是我的代码,一直运行到免费(右); more like it completes merge sort then has an error, any solutions?
更像是它完成合并排序然后有错误,任何解决方案?
#include <stdio.h>
#include <stdlib.h>
void bubble_sort(int *l, int len) {
// Iterate through the list
for (int i = 0; i < len; i++) {
// Iterate through the list
for (int j = 0; j < len - 1; j++) {
// If the current element is greater than the next element, swap them
if (l[j] > l[j + 1]) {
// Swap the elements
int temp = l[j];
l[j] = l[j + 1];
l[j + 1] = temp;
// Print the list
for (int k = 0; k < len; k++) {
printf("%d ", l[k]);
}
printf("\n");
}
}
}
}
void selection_sort(int *l, int len) {
// Iterate through the list
for (int i = 0; i < len; i++) {
// Set the minimum index to the current index
int min_index = i;
// Iterate through the list
for (int j = i + 1; j < len; j++) {
// If the current element is less than the minimum element, set the minimum index to the current index
if (l[j] < l[min_index]) {
min_index = j;
}
}
// Swap the elements
int temp = l[i];
l[i] = l[min_index];
l[min_index] = temp;
// Print the list
for (int k = 0; k < len; k++) {
printf("%d ", l[k]);
}
printf("\n");
}
}
void insertion_sort(int *l, int len) {
// Iterate through the list
for (int i = 1; i < len; i++) {
// Set the current index to the current index
int j = i;
// While the current index is greater than 0 and the previous element is greater than the current element, swap them
while (j > 0 && l[j - 1] > l[j]) {
// Swap the elements
int temp = l[j - 1];
l[j - 1] = l[j];
l[j] = temp;
// Decrement the current index
j--;
}
// Print the list
for (int k = 0; k < len; k++) {
printf("%d ", l[k]);
}
printf("\n");
}
}
void merge(int *left, int left_len, int *right, int right_len) {
// Create a new list
int *result = malloc((left_len + right_len) * sizeof(int));
// Set the left index to 0 and the right index to 0
int i = 0;
int j = 0;
// While the left index is less than the length of the left list and the right index is less than the length of the right list
while (i < left_len && j < right_len) {
// If the left element is less than or equal to the right element, append the left element to the result list and increment the left index
if (left[i] <= right[j]) {
result[i + j] = left[i];
i++;
}
// Else, append the right element to the result list and increment the right index
else {
result[i + j] = right[j];
j++;
}
}
// Append the remaining elements in the left list to the result list
for (int k = i; k < left_len; k++) {
result[k + j] = left[k];
}
// Append the remaining elements in the right list to the result list
for (int k = j; k < right_len; k++) {
result[k + i] = right[k];
}
// Print the result list
for (int k = 0; k < left_len + right_len; k++) {
printf("%d ", result[k]);
}
printf("\n");
// Copy the result list to the original list
for (int k = 0; k < left_len + right_len; k++) {
left[k] = result[k];
}
// Free the result list
free(result);
}
void merge_sort(int *l, int len) {
// If the list is empty or has one element, return the list
if (len <= 1) {
return;
}
// Set the middle index to the length of the list divided by 2
int mid = len / 2;
// Set the left list to the first half of the list
int *left = malloc(mid * sizeof(int));
for (int i = 0; i < mid; i++) {
left[i] = l[i];
}
// Set the right list to the second half of the list
int *right = malloc((len - mid) * sizeof(int));
for (int i = mid; i < len; i++) {
right[i - mid] = l[i];
}
// Sort the left list
merge_sort(left, mid);
// Sort the right list
merge_sort(right, len - mid);
// Merge the left list and the right list
merge(left, mid, right, len - mid);
// Free the left list and the right list
free(left);
free(right); //Error ln 142, in picture below
}
int binary_search(int *l, int len, int target) {
// Set the low index to 0 and the high index to the length of the list minus 1
int low = 0;
int high = len - 1;
// While the low index is less than or equal to the high index
while (low <= high) {
// Set the middle index to the sum of the low index and the high index divided by 2
int mid = (low + high) / 2;
// If the middle element is equal to the target, return the middle index
if (l[mid] == target) {
return mid;
}
// Else if the middle element is less than the target, set the low index to the middle index plus 1
else if (l[mid] < target) {
low = mid + 1;
}
// Else, set the high index to the middle index minus 1
else {
high = mid - 1;
}
}
// If the target is not found, return -1
return -1;
}
int main() {
// Create a list
int l[] = {17, 36, 3, 10, 29, 42, 34, 8};
int len = sizeof(l) / sizeof(l[0]);
// Print the list
printf("Bubble Sort:\n");
// Sort the list using bubble sort
bubble_sort(l, len);
// Print the list
printf("Selection Sort:\n");
// Sort the list using selection sort
selection_sort(l, len);
// Print the list
printf("Insertion Sort:\n");
// Sort the list using insertion sort
insertion_sort(l, len);
// Print the list
printf("Merge Sort:\n");
// Sort the list using merge sort
merge_sort(l, len);
// Print the list
printf("Binary Search:\n");
// Search for the target in the list using binary search
printf("%d\n", binary_search(l, len, 42));
return 0;
}
So I rewrote the code from python to C, and debugging in GDB gives me the error in the screenshot.于是我把python的代码改写成C,在GDB调试给我截图报错。
I've tried to edit the function itself to rectify the memory issue but it wouldn't work so i reverted back to this and hope someone has some more insight.我试图编辑 function 本身来纠正 memory 问题,但它不起作用,所以我又回到了这里,希望有人有更多的见解。
The segfault is triggered in merge()
used by merge_sort()
.段错误在
merge_sort()
merge()
中触发。 Everything else is irrelevant.其他一切都无关紧要。
In merge_sort()
you copy half of the input array l
into a newly allocated array left
and the other half into another newly allocated array right
.在
merge_sort()
中,您将输入数组l
的一半复制到新分配的数组left
中,另一半复制到另一个新分配的数组right
中。 Then recursively merge_sort()
those two halves which is fine.然后递归
merge_sort()
这两半就可以了。 To combine the two halves merge()
is called where you incorrectly assume that the left and right arrays are allocated consecutively:合并两半
merge()
在您错误地假设左和右 arrays 是连续分配的地方被调用:
for (int k = 0; k < left_len + right_len; k++) {
left[k] = result[k];
}
The minimal fix is to make the assumption valid:最小的修复是使假设有效:
void merge_sort(int *l, int len) {
if (len <= 1) {
return;
}
int mid = len / 2;
int *left = malloc(len * sizeof(int));
for (int i = 0; i < mid; i++) {
left[i] = l[i];
}
int *right = left + mid;
for (int i = mid; i < len; i++) {
right[i - mid] = l[i];
}
merge_sort(left, mid);
merge_sort(right, len - mid);
merge(left, mid, right, len - mid);
free(left);
}
A even better resolution would be to:更好的解决方案是:
main()
the task of duplicating the input array instead of doing that in your sort algorithm.main()
,而不是在您的排序算法中执行该任务。 This allows merge_sort()
to operate on the input array in-place ( merge()
still uses the temporary array).merge_sort()
对输入数组进行操作( merge()
仍然使用临时数组)。right
array pointer argument to merge()
.merge()
的right
数组指针参数。 This documents that the left and right arrays are part of the the same array.merge()
and merge_sort()
interface so the length argument is before the array argument so you can document how they relate.merge()
和merge_sort()
接口,使长度参数位于数组参数之前,这样您就可以记录它们之间的关系。merge_sort()
and pass it to merge_sort2()
and merge2()
.merge_sort()
中分配一次合并所需的临时空间,并将其传递给merge_sort2()
和merge2()
。 That way you only have O(n)
space overhead instead of O(n*log(n))
.O(n)
空间开销而不是O(n*log(n))
。 It is worth pointing out that malloc()
may require a kernel context switch which in turn would be the most expensive operation th the merge()
+ merge_sort()
implementation.malloc()
可能需要 kernel 上下文切换,这反过来又是merge()
+ merge_sort()
实现中最昂贵的操作。 Doing 1 instead of n*log(n) calls to malloc()
could be a significant (constant) factor in run-time.malloc()
执行 1 而不是 n*log(n) 调用可能是运行时中的一个重要(常数)因素。 Sharing the temporary space, however, comes a cost as you would no longer be able to do the otherwise non-overlapping merge sorts in parallel.size_t
to int
for lengths.size_t
而不是int
。 sizeof() in particular returns a size_t
value, and the cast to the (signed) int
will be problematic for sizes greater than INTMAX
. size_t
值,并且对于大于INTMAX
的大小,转换为(带符号的) int
会出现问题。memcpy()
instead of explicit loops when possible.memcpy()
而不是显式循环。 memcpy()
is highly optimized, and succinctly expresses intent. memcpy()
经过高度优化,并简洁地表达了意图。sizeof()
.sizeof()
。 The former is robust if you change the type of the variable where the latter requires a code change if you didn't use a typedef
for the type.typedef
,则后者需要更改代码。print()
function so you don't need the debug print statements in the sorting functions themselves.print()
function 这样您就不需要排序函数本身中的调试打印语句。#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void merge(size_t left_len, size_t right_len, int l[left_len + right_len]) {
int *result = malloc((left_len + right_len) * sizeof(*l));
int i = 0;
int j = 0;
while (i < left_len && j < right_len) {
if (l[i] <= l[left_len + j]) {
result[i + j] = l[i];
i++;
} else {
result[i + j] = l[left_len + j];
j++;
}
}
memcpy(result + i + j, l + i, (left_len - i) * sizeof(*l));
memcpy(result + left_len + j, l + left_len + j, (right_len - j) * sizeof(*l));
memcpy(l, result, (left_len + right_len) * sizeof(*l));
free(result);
}
void merge_sort(size_t len, int l[len]) {
if (len < 2) return;
int mid = len / 2;
merge_sort(mid, l);
merge_sort(len - mid, l + mid);
merge(mid, len - mid, l);
}
void print(size_t len, int a[len]) {
for(size_t i = 0; i < len; i++) {
printf("%d%s", a[i], i + 1 < len ? ", " : "\n");
}
}
int main() {
int l[] = {17, 36, 3, 10, 29, 42, 34, 8};
size_t len = sizeof(l) / sizeof(*l);
int l2[len];
memcpy(l2, l, sizeof(l));
merge_sort(len, l2);
print(len, l2);
}
and it returns:它返回:
3, 8, 10, 17, 29, 34, 36, 42
valgrind is happy: valgrind 很高兴:
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.