如何调试含pthread的C代码并修复数组首索引垃圾值问题
问题:Pthread线程排序后主线程数组首有效元素出现垃圾值
问题描述
编写了一段基于pthread的C语言代码,功能为接收用户输入数组,拆分后通过两个线程分别执行升序归并排序(mergeSortA)、降序归并排序(mergeSortD)。线程内部输出的排序结果正常,但主线程输出时,数组的首有效索引(索引1,索引0用于存储数组长度)始终出现垃圾值,需调试修复。
原代码
#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); }
问题根源
pthread_join参数错误:pthread_join的第二个参数是void**类型,用于接收线程退出时返回的指针。原代码中pthread_join(t1, (void*)arr1);直接将arr1的地址强转为void*,导致线程返回的指针值被写入arr1的起始位置(即索引0和索引1),破坏了原有的数组数据,这是首有效元素出现垃圾值的直接原因。- 线程函数内存泄漏:线程函数中
int* arr = (int*)malloc(sizeof(int)*1000);分配内存后,立刻被传入的args指针覆盖,导致内存泄漏。
修复方案
- 修正
pthread_join调用:由于线程直接操作主线程传入的栈数组,无需接收返回值,直接将第二个参数设为NULL即可。 - 移除线程函数中多余的
malloc调用,直接使用传入的指针。
修复后的代码
#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) { 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) { 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) { 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) { 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*)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(NULL); } void* sort_d(void* args) { int* 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(NULL); } 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, NULL); pthread_join(t2, NULL); //After Sorting printf("Main Thread:\n"); display2(arr1, k1); display2(arr2, k2); }
验证说明
修复后,线程直接修改主线程的栈数组,pthread_join不再破坏数组数据,主线程输出的数组首有效元素将和线程内部输出的一致,垃圾值问题解决。
内容的提问来源于stack exchange,提问作者Debak Roy
相关产品推荐
相关产品推荐

