如何使用线程调试此 C 代码,以及如何修复该问题

How to debug this C code using threads, and how to fix the issue

提问人:Debak Roy 提问时间:10/31/2023 最后编辑:halferDebak Roy 更新时间:11/8/2023 访问量:118

问:

代码如下:


#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>

void display(int *arr, int size) {
    int i;
    for(i=0; i<size; i++)
        printf("%d ", arr[i]);

    printf("\n");
}

void display2(int *arr, int size) {
    int i;
    for(i=1; i<size; i++)
        printf("%d ", arr[i]);
        
    printf("\n");
}


void mergeA(int* arr, int lb, int ub, int mid) {
//  printf("Inside mergeA\n");
    int i=lb, j=mid+1, k=lb;
    int newarr[1000];

    while(i<=mid && j<=ub) {
        if(arr[i] > arr[j])
            newarr[k++] = arr[j++];
        else
            newarr[k++] = arr[i++];
    }
    
    for(; i<=mid; i++)
        newarr[k++] = arr[i];
    for(; j<=ub; j++)
        newarr[k++] = arr[j];

    for(i=lb; i<=ub; i++)
        arr[i] = newarr[i];
}
void mergeD(int* arr, int lb, int ub, int mid) {
//  printf("Inside mergeD\n");
    int i=lb, j=mid+1, k=lb;
    int newarr[1000];

    while(i<=mid && j<=ub) {
        if(arr[i] < arr[j])
            newarr[k++] = arr[j++];
        else
            newarr[k++] = arr[i++];
    }
    
    for(; i<=mid; i++)
        newarr[k++] = arr[i];
    for(; j<=ub; j++)
        newarr[k++] = arr[j];

    for(i=lb; i<=ub; i++)
        arr[i] = newarr[i];
}


void mergeSortA(int* arr, int lb, int ub) {
//  printf("Inside mergeSortA\n");
    if(lb<ub) {
        int mid = (lb+ub)/2;
        mergeSortA(arr, lb, mid);
        mergeSortA(arr, mid+1, ub);
        mergeA(arr, lb, ub, mid);
    }
}

void mergeSortD(int* arr, int lb, int ub) {
//  printf("Inside mergeSortD\n");
    if(lb<ub) {
        int mid = (lb+ub)/2;
        mergeSortD(arr, lb, mid);
        mergeSortD(arr, mid+1, ub);
        mergeD(arr, lb, ub, mid);
    }
}

void* sort_a(void* args) {
    int* arr = (int*)malloc(sizeof(int)*1000);
    arr = (int*)args;
    int size = arr[0];

    printf("Inside Sort A: ");
    display2(arr, size);
    
    mergeSortA(arr, 1, size-1);
    printf("After Sort A: ");
    display2(arr, size);
    pthread_exit((void*)arr);
}

void* sort_d(void* args) {
    int* arr = (int*)malloc(sizeof(int)*1000);
    arr = (int*)args;
    int size = arr[0];

    printf("Inside Sort D: ");
    display2(arr, size);
    
    mergeSortD(arr, 1, size-1);
    printf("After Sort D: ");
    display2(arr, size);
    pthread_exit((void*)arr);
}

int main() {
    pthread_t t1, t2;
    int arr[1000];
    int i=0, j, k1=1, k2=1;

    //Taking the array as input
    while(1) {
        printf("Enter an element or 'quit' to stop input: ");
        
        char input[100];
        scanf("%s", input);

        if(strcmp(input, "quit") == 0)
            break;

        arr[i++] = atoi(input);
    }
    printf("The Array:\n");
    display(arr, i);

    //Spliting the array into two
    int arr1[1000], arr2[1000];
    for(j=0; j<i; j++) {
        if(j<i/2)
            arr1[k1++]=arr[j];
        else
            arr2[k2++]=arr[j];
    }
    //Storing size in index 0
    arr1[0] = k1;
    arr2[0] = k2;

    //Creating the threads
    pthread_create(&t1, NULL, &sort_a, (void*)arr1);
    pthread_create(&t2, NULL, &sort_d, (void*)arr2);

    //Joining the threads
    pthread_join(t1, (void*)arr1);
    pthread_join(t2, (void*)arr2);

    //After Sorting
    printf("Main Thread:\n");
    display2(arr1, k1);
    display2(arr2, k2);
}

我希望输出与函数(sort_a 和 sort_d)中的输出相同,但第一个索引中的元素始终是垃圾值。 注意:在这种情况下,第一个索引是 1,因为我将长度存储在第 0 个索引中

输出图像

如您所见,主线程中的输出不正确。

C 多线程合并 排序

评论

2赞 Jeremy Friesner 10/31/2023
此链接中有一些很好的调试建议: ericlippert.com/2014/03/05/how-to-debug-small-programs
1赞 9769953 10/31/2023
请创建一个最小的可重现示例(注意:最小)。此外,将输出作为文本发布,格式化为代码块;不是作为图像。
1赞 teapot418 10/31/2023
pthread_join(t1, (void*)arr1)将用结果覆盖数组中的前两个(假设是 64 位架构)int。您没有检查结果,因此请考虑将其存储在其他地方。
4赞 n. m. could be an AI 10/31/2023
int* arr = (int*)malloc(sizeof(int)*1000); arr = (int*)args; 我们又来了
2赞 n. m. could be an AI 10/31/2023
int pthread_join(pthread_t thread, void **retval);你明白为什么第二个参数的类型是而不是吗?void**void*

答:

0赞 rcgldr 11/1/2023 #1

在 MergeD 中,比较应该是:

        if(arr[i] > arr[j])    /* not if(arr[i] < arr[j]) */

sort_a 和 sort_d malloc 数组,但切勿释放它们。它们应释放分配的内存。两个合并函数都应使用 malloc 而不是使用大小为 1000 的局部数组,以便可以对更大的数组进行排序。

两个线程完成后,需要进行最终合并。


不需要为这两个线程设置一组单独的函数。

作为使用索引 0 表示数组大小的替代方法,pthread_create可以将指向结构的指针作为参数传递,其中结构将包含指向数组中元素的指针和大小。

1赞 storsan 11/8/2023 #2

不应将合并子数组作为参数传递给作为线程运行的排序函数。根据下面粘贴的 POSIX 线程规范函数原型,终止调用线程,并使该值可用于与终止线程的任何成功连接。该函数暂停调用线程的执行,直到目标线程终止。使用非 NULL 参数参数成功调用返回时,终止线程传递到的值应在 引用的位置中可用。arrpthread_exit()pthread_exit()value_ptrpthread_join()pthread_join()value_ptrpthread_exit()value_ptr

void pthread_exit(void *value_ptr);
int pthread_join(pthread_t thread, void **value_ptr);

您应该通过以下方式从中获取值:main()pthread_exit()

int main() {
  ...
  ...
  int *result1=0;
  int *result2=0;
  ...
  ...
  pthread_join(t2, (void **) &result2);
  pthread_join(t1, (void **) &result1);
  ...
  printf ("\nstatus returned thread t1=%d", *result1);
  printf ("\nstatus returned thread t2=%d", *result2);
  ...
}

在排序函数中,设置如下。不要为 call 参数引用本地 /stack 变量。value_ptrpthread_exit()value_ptr

void * sort_d(void * args) {
  ...
  int *retval;
  retval = (int *) (malloc (sizeof (int));
  ...
  *retval = 0; // any value you want to return
  pthread_exit(retval);
}

或者,您可以在排序函数中发出返回值,而不是调用 .如下图所示,由于 sort 函数的返回值也用作线程的退出值:value_ptr pthread_exit()retval

void * sort_d(void * args) {
  ...
  int *retval;
  retval = (int *) (malloc (sizeof (int));
  ...
  *retval = 0 // set to any value you want to return
  return retval;
}

pthread 函数 ,如果成功,则返回零。您可能需要检查这些函数的返回值是否存在任何错误。pthread_create()pthread_join()