【发布时间】:2021-09-18 00:11:25
【问题描述】:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student{
int grade;
int enrollCode;
}student;
typedef struct colVoidStar{
int capacity;
int num_itens_curr;
void **arr;
int current_pos;
}colVoidStar;
colVoidStar *colCreate(int capacity){
if(capacity > 0){
colVoidStar *c = malloc(sizeof(colVoidStar));
if(c != NULL){
c->arr = (void**)malloc(sizeof(void*)*capacity);
if( c->arr != NULL){
c->num_itens_curr = 0;
c->capacity = capacity;
return c;
}
free(c->arr);
}
free(c);
}
return NULL;
}
int colInsert(colVoidStar *c, void *item){
if(c != NULL){
if(c->num_itens_curr < c->capacity){
c->arr[c->num_itens_curr] = (student*)item;
c->num_itens_curr++;
return 1;
}
}
return 0;
}
void *colRemove(colVoidStar *c, void *key, int compar1(void* a, void* b)){
int(*ptrCompar)(void*, void*) = compar1;
student* eleRemoved;
if(c != NULL){
if(c->num_itens_curr > 0){
int i = 0;
for(i; i < c->num_itens_curr; i++){
if(ptrCompar((void*)key, (void*)c->arr[i]) == 0){
eleRemoved = (student*)c->arr[i];
for(int j = i; j < c->num_itens_curr; j++){
c->arr[i] = c->arr[i + 1];
c->arr[i + 1] = 0;
}
return (void*)eleRemoved;
}
return NULL;
}
}
}
return NULL;
}
int compar1(void *a, void*b){
int key;
student *item;
key = *(int*)a;
item = (student*)b;
return (int)(key - item->enrollCode);
}
int main(){
int finishProgram = 0, choose, capacity, returnInsert, removeEnroll;
colVoidStar *c;
student *a, *studentRemoved;
while(finishProgram != 9){
printf("-----------------panel-----------------------\n");
printf("Type: \n");
printf("[1] to create a collection;\n");
printf("[2] to insert a student;\n");
printf("[3] to remove some student of collection;\n");
printf("--------------------------------------------------------\n");
scanf("%d", &choose);
switch(choose){
case 1:
printf("Type the maximum of students the collection will have: \n");
scanf("%d", &capacity);
c = (colVoidStar*)colCreate(capacity);
if(c == NULL){
printf("Error in create collection!\n");
}
break;
case 2:
if(c->num_itens_curr < capacity){
a = (student*)malloc(sizeof(student));
printf("%d student:(type the Grade and the Enroll code, back-to-back)\n", c->num_itens_curr + 1);
scanf("%d %d", &a->grade, &a->enrollCode);
returnInsert = colInsert(c, (void*)a);
if(returnInsert == 1){
for(int i = 0; i < c->num_itens_curr; i++){
printf("The student added has grade = %d e enrollCode = %d \n", (((student*)c->arr[i])->grade), ((student*)c->arr[i])->enrollCode);
}
}else{
printf("the student wasn't added in the collection\n");
}
}else{
printf("it's not possible to add more students to the colletion, since the limit of elements was reached!");
}
break;
case 3:
printf("Type an enrollcode to remove the student attached to it:\n");
scanf("%d", &removeEnroll);
studentRemoved = (student*)colRemove(c, &removeEnroll, compar1(&removeEnroll, c->arr[0]));
if(studentRemoved != NULL)
printf("the student removed has grade = %d and enrollcode %d.", studentRemoved->grade, studentRemoved->enrollCode);
else
printf("the number typed wasn't found");
break;
}
}
return 0;
}
---> 正如您所意识到的,至少在这一点上,我正在尝试做的是访问和删除学生收藏的项目(student* 最初将假定为void* 类型) (void**arr) 使用某种注册码。但是,我遇到了分段错误的问题,无法理解为什么以及如何解决它们,因此我的问题就在那里。调试代码我发现错误在于:Remove 函数内部的if(ptrCompar((void)key, (void**)*c->arr[i]) == 0) 和Compar1 内部的return (int)(key - item->matricula)。
此外,如果您能指出一些有助于我理解如何处理此类问题的文章/文档/任何内容,我将不胜感激。
【问题讨论】:
-
看来你应该以此为契机学习如何使用调试器。逐句逐句遍历代码,记下所有指针及其指向的地址,并在传递给
free时添加注释。然后当崩溃发生时,您会看到哪个指针被取消引用(以及如何!)并与您的指针列表进行比较。您是否可能试图取消引用传递给free的指针?空指针?或者可能是一个未初始化的指针? -
colRemove(c, &removeEnroll, compar1(&removeEnroll, c->arr[0]));的最后一个参数与形参不匹配。形参是函数指针,但实参compar1(&removeEnroll, c->arr[0])是int。试试colRemove(c, &removeEnroll, compar1);。 -
colRemove根本不应该使用(student*)如果colVoidStar函数应该是通用的。 -
colRemove的内部循环使用了错误的变量来索引c->arr[],并且循环终止条件为 1。 -
如果您能显示您使用的输入,那么重现您的问题会更容易,或者如果您通过更改
main函数以使用硬编码调用其他函数来简化程序,那就更好了数据以重现问题的方式。
标签: c pointers segmentation-fault void-pointers void-safety