我有一个包含函数指针和函数指针数组的结构。我将第一个指针(不是数组)作为函数的参数传递,该函数应该告诉我整数数组是否已排序(它可以按升序或降序排列,这是由 compFct 定义的,它是指向参数中给定函数的指针)。
不幸的是,该函数正在更改我的结构中指针数组中的值(但没有更改我指向参数中给定函数的指针的值)。
使用 gdb 我设法知道何时对我的数组进行了更改。它似乎在 printSorted 函数中的第一个 printf 之后被修改。
我的类型定义:
typedef int (*PtrCompFct)(int, int);
typedef int (*PtrSortFct)(int*, int, int, PtrCompFct);
结构:
typedef struct
{
int nbFct;
PtrCompFct compFct;
PtrSortFct *sortFct;
} SortCompFct_s;
这是我调用函数的方式(userChoices 是 SortCompFct_s 类型):
printSorted(myArr, myArrSize, userChoices->compFct);
以及正在改变我的结构的功能:
int printSorted(int *arr, int arrSize, PtrCompFct compFct)
{
for (int i=0; i<(arrSize-1); i++)
{
if (compFct(arr[i+1], arr[i]))
{
//this is when my array of pointers to function is modified
printf("The array isn't sorted\n\n");
return 0;
}
}
printf("The array is sorted\n\n");
return 1;
}
在 printf 之前使用 gdb 我有:
(gdb) print main::userChoices->sortFct[0]
$36 = (PtrSortFct) 0x5555555548ea <quickSort>
及之后:
(gdb) print main::userChoices->sortFct[0]
$37 = (PtrSortFct) 0x7fffffffddc0
如您所见,指向我的 quickSort 函数的指针已被修改。
编辑:包括简化和可验证的代码,问题是这段代码工作正常,即使使用 printSorted 函数也是如此
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int (*PtrCompFct)(int, int);
typedef int (*PtrSortFct)(int*, int, int, PtrCompFct);
typedef struct
{
int nbFct;
PtrCompFct compFct;
PtrSortFct *sortFct;
} SortCompFct_s;
typedef SortCompFct_s *PtrSortCompFct_s;
void initTab(int *arr, int arrSize)
{
time_t t;
srand(time(&t));
for (int i=0; i<arrSize; i++)
{
arr[i] = rand();
}
}
int ascendingSort(int elmt1, int elmt2)
{
return (elmt1 < elmt2);
}
int descendingSort(int elmt1, int elmt2)
{
return (elmt1 > elmt2);
}
void switche(int *arr, int ind1, int ind2)
{
int temp = arr[ind1];
arr[ind1] = arr[ind2];
arr[ind2] = temp;
}
int bubbleSort(int *arr, int ind1, int ind2, PtrCompFct fctComp)
{
int sorted;
for (int i=ind1; i<ind2; i++)
{
sorted = 1;
for (int j=0; j<ind2; j++)
{
if (fctComp(arr[j+1], arr[j]))
{
switche(arr, j, j+1);
sorted = 0;
}
}
if (sorted) return 0;
}
return 0;
}
void printArr(int *arr, int arrSize)
{
for (int i=0; i<arrSize; i++)
{
printf("%16d\n", arr[i]);
}
}
int printSorted(int *arr, int arrSize, PtrCompFct compFct)
{
for (int i=0; i<arrSize-1; i++)
{
if (compFct(arr[i+1], arr[i]))
{
//this is when my array of pointers to function is modified
printf("The array isn't sorted\n\n");
return 0;
}
}
printf("The array is sorted\n\n");
return 1;
}
PtrSortCompFct_s menu(void)
{
PtrSortCompFct_s userChoices;
PtrSortFct arrSortFct[] = {bubbleSort};
if ((userChoices = malloc(3*sizeof(int))) != NULL)
{
userChoices->nbFct = 1;
userChoices->compFct = ascendingSort;
userChoices->sortFct = arrSortFct;
}
return userChoices;
}
int main(void)
{
int arrSize = 10;
int arr[arrSize];
initTab(arr, arrSize);
PtrSortCompFct_s userChoices;
if ((userChoices = malloc(3*sizeof(int))) != NULL) userChoices = menu();
printArr(arr, arrSize);
printSorted(arr, arrSize, userChoices->compFct);
userChoices->sortFct[0](arr, 0, arrSize-1, userChoices->compFct);
printArr(arr, arrSize);
printSorted(arr, arrSize, userChoices->compFct);
return 0;
}
最佳答案
With gdb before the printf I have: ... and after:
问题的根本原因在于您如何初始化 userChoices->sortFct
(您没有显示执行此初始化的代码)。
该数组指向悬挂 堆或栈内存,调用printf
会覆盖该内存。
if ((userChoices = malloc(6*sizeof(int))) != NULL) userChoices = menu();
该代码完全是伪造的:为 userChoices
堆分配内存,然后立即用 menu()
的返回值覆盖 userChoices
仅用于泄漏内存。如评论中所述,6*sizeof(int)
也是完全伪造的大小。
我猜你的 menu()
看起来像这样:
struct SortCompFct_s* menu()
{
struct SortCompFct_s ret;
ret.compFct = &SomeFunc;
ret.sortFct = malloc(...);
ret.sortFct[0] = &quickSort;
return &ret; // Oops: returning address of a local!
}
如果这实际上是您所做的,那么悬挂堆栈正是您的问题。您应该打开最大编译器警告(如果使用 GCC,则为 -Wall -Wextra
),以便编译器告诉您您做错了什么。
更新:
我的猜测很接近:
PtrSortCompFct_s menu(void)
{
PtrSortCompFct_s userChoices;
PtrSortFct arrSortFct[] = {bubbleSort};
if ((userChoices = malloc(3*sizeof(int))) != NULL)
{
userChoices->nbFct = 1;
userChoices->compFct = ascendingSort;
userChoices->sortFct = arrSortFct;
}
return userChoices;
}
问题是 userChoices->sortFct
指向本地(堆栈)变量 arrSortFct
。从 menu
返回后,该局部变量变得无效,此时 userChoices->sortFct
指向悬空堆栈(正如我猜测的那样)。
这是编写此函数的正确方法(为清楚起见省略了 malloc
返回的错误检查):
PtrSortCompFct_s menu(void)
{
PtrSortCompFct_s userChoices;
PtrSortFct arrSortFct[] = {bubbleSort};
if ((userChoices = malloc(sizeof(*userChoices)) != NULL)
{
userChoices->nbFct = 1;
userChoices->compFct = ascendingSort;
userChoices->sortFct = malloc(sizeof(arrSortFct));
memcpy(userChoices->sortFct, arrSortFct, sizeof(arrSortFct));
}
return userChoices;
}
您还应该像这样修复您的 main
:
PtrSortCompFct_s 用户选择;
PtrSortCompFct_s userChoices = menu();
... use userChoices ...
free(userChoices->sortFct);
free(sortFct);
return 0;
关于c - 为什么调用函数会修改参数中未给出的指向函数的指针数组的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54728582/