簡體   English   中英

我不確定為什么我在 C 中的代碼會免費給我一個分段錯誤,有什么想法嗎?

[英]I'm not sure why my code in C is giving me a segmentation fault at free, any ideas?

所以這是我的代碼,一直運行到免費(右); 更像是它完成合並排序然后有錯誤,任何解決方案?

#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;
}

於是我把python的代碼改寫成C,在GDB調試給我截圖報錯。

GDB 黨衛軍

我試圖編輯 function 本身來糾正 memory 問題,但它不起作用,所以我又回到了這里,希望有人有更多的見解。

段錯誤在merge_sort() merge()中觸發。 其他一切都無關緊要。

merge_sort()中,您將輸入數組l的一半復制到新分配的數組left中,另一半復制到另一個新分配的數組right中。 然后遞歸merge_sort()這兩半就可以了。 合並兩半merge()在您錯誤地假設左和右 arrays 是連續分配的地方被調用:

    for (int k = 0; k < left_len + right_len; k++) {
        left[k] = result[k];
    }

最小的修復是使假設有效:

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);
}

更好的解決方案是:

  1. 將被測代碼和您的測試工具嚴格分開。 在這種情況下,您希望將復制輸入數組的任務委托給main() ,而不是在您的排序算法中執行該任務。 這允許merge_sort()對輸入數組進行操作( merge()仍然使用臨時數組)。
  2. 消除merge()right數組指針參數。 該文檔表明左右 arrays 是同一數組的一部分。
  3. 重構merge()merge_sort()接口,使長度參數位於數組參數之前,這樣您就可以記錄它們之間的關系。
  4. (不固定)。 您可以在merge_sort()中分配一次合並所需的臨時空間,並將其傳遞給merge_sort2()merge2() 這樣你只有O(n)空間開銷而不是O(n*log(n)) 值得指出的是, malloc()可能需要 kernel 上下文切換,這反過來又是merge() + merge_sort()實現中最昂貴的操作。 malloc()執行 1 而不是 n*log(n) 調用可能是運行時中的一個重要(常數)因素。 然而,共享臨時空間是有代價的,因為您將無法再並行執行其他非重疊合並排序。
  5. 對於長度,首選類型size_t而不是int sizeof() 特別返回一個size_t值,並且對於大於INTMAX的大小,轉換為(帶符號的) int會出現問題。
  6. 盡可能使用memcpy()而不是顯式循環。 memcpy()經過高度優化,並簡潔地表達了意圖。
  7. 更喜歡將變量而不是類型傳遞給sizeof() 如果您更改變量的類型,前者是健壯的,而如果您沒有對類型使用typedef ,則后者需要更改代碼。
  8. 最后,我添加了一個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);
}

它返回:

3, 8, 10, 17, 29, 34, 36, 42

valgrind 很高興:

ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM