C语言 释放通用函数/访问冲突读取错误位置中的特定类型的数据



我正在为赋值编写此代码,这些函数应该是通用的,由用户决定是使用整数还是字符串。 显然,我为这两种类型的操作编写了特定的函数。 代码中留下的唯一问题是当我尝试释放 int 类型分配的内存时,我得到以下内容:

Exception thrown at 0x0F24904D (ucrtbased.dll) in ConsoleApplication7.exe: 0xC0000005: Access violation reading location 0x00000006.

我只有在调试时才会得到这个,但是当我尝试执行操作并在结束程序之前冻结几秒钟时,在没有调试的情况下编译只会停止。

以下是整个代码:

页眉:

#ifndef _HEADER_H
#define _HEADER_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
typedef enum { FALSE, TRUE } BOOL;
/* defining specific function names*/
typedef int(*compare_func)(void*, void*);
typedef void(*print_func)(void*);
typedef void(*free_func)(void*);
/* defining struct names and pointers*/
typedef struct set Set;
typedef struct set* PSet;
typedef struct list List;
typedef struct list* PList;

/* creating and initialzing a set*/
List* createSet(compare_func cmp_fnc, print_func prnt_fnc, free_func free_fnc);
/* finding the biggest value in the set*/
void* findMax(PList List);
/* finding the smallest value in the set*/
void* findMin(PList List);
/* finding an element in the set*/
BOOL findInSet(PList List, void* val);
/* function for finding the size of the list*/
int setSize(PList list);
/* inserting a new element.*/
BOOL addToSet(PList List, void *data);
/* deleting an element, pointered by todel*/
BOOL deleteFromSet(PList list, void *todel);
/* print the elements in the set */
void printAll(PList list);
/* deleting the entire set */
void deleteSet(PList list);
#endif

实现:

#include "Header.h"
struct set      // Set struct for doubly-linked list
{
void* data;
struct  set *next, *prev;
};
struct list      // List struct
{
int ListSize;
Set *head;
Set *tail;
compare_func compare;
print_func print;
free_func free;
};

List* createSet(compare_func cmp_fnc, print_func prnt_fnc, free_func free_fnc)    // Function for initializing and creating a set
{
PList LIST;
LIST = (PList)malloc(sizeof(List));
if (LIST == NULL)
{
printf("Error! Memory allocation failed.n");
exit(1);
}
LIST->ListSize = 0;
LIST->head = NULL;
LIST->tail = NULL;
LIST->compare = cmp_fnc;
LIST->print = prnt_fnc;
LIST->free = free_fnc;
return LIST;
}
void* findMax(PList List)         // Function for finding the biggest value in a set
{
if (List->head == NULL)     // If the set is empty
return NULL;
PSet temp;
void* max = List->head->data;
temp = List->head;
while (temp)
{
if (List->compare(temp->data, max) == 1)      // Finding the biggest value
max = temp->data;
temp = temp->next;    // Moving to the next node
}
return max;
}

void* findMin(PList List)         // Function for finding the smallest value in a set
{
if (List->head == NULL)        // If the set is empty
return NULL;
PSet temp;
void* min = List->head->data;
temp = List->head;
while (temp)
{
if (List->compare(temp->data, min) == -1)       // Finding the smallest value
min = temp->data;
temp = temp->next;       // Moving to the next node
}
return min;
}

BOOL findInSet(PList List, void* val)        // Function for checking whether a given character is in the set
{
if (List->head == NULL)    // If the list is empty
return FALSE;
PSet temp;
temp = List->head;
while (temp)
{
if (List->compare(temp->data, val) == 0)        // If the character exists
return TRUE;
temp = temp->next;     // Moving to the next node
}
return FALSE;
}

int setSize(PList list)
{
return list->ListSize;
}

BOOL addToSet(PList List, void *data)       // Function for adding an item to the set
{
PSet temp, CurrentNode;
CurrentNode = List->head;
temp = (PSet)malloc(sizeof(Set));
if (temp == NULL)           // If the allocation failed return false
return FALSE;
temp->data = data;       // Filling the temp with the data
temp->next = NULL;
temp->prev = NULL;
if (List->head == NULL)      // If the list is empty
{
List->head = temp;
List->tail = temp;
List->ListSize++;
return TRUE;
}
else {
while (CurrentNode)          // Loop for checking whether the inserted character exists in the list
{
if (List->compare(data, CurrentNode->data) == 0) return FALSE;
CurrentNode = CurrentNode->next;
}
List->tail->next = temp;   // Adding the node to the list
temp->prev = List->tail;
List->tail = temp;     // Updating the tail
List->ListSize++;
return TRUE;
}
}

BOOL deleteFromSet(PList list, void *todel)         // Function for deleteing an item from a set
{
PSet nodeToDel;
if (list->head == NULL)      // If the list is empty
return FALSE;
if (list->compare(todel, list->head->data) == 0)    // If the node to be deleted is the head
{
nodeToDel = list->head;
list->head = list->head->next;
if (list->head != NULL)
list->head->prev = NULL;
list->free(nodeToDel->data);
free(nodeToDel);
list->ListSize--;
return TRUE;
}
else if (list->compare(todel, list->tail->data) == 0)         // If the node to be deleted is the tail
{
nodeToDel = list->tail;
list->tail = list->tail->prev;
list->tail->next = NULL;
list->free(nodeToDel->data);
free(nodeToDel);
list->ListSize--;
return TRUE;
}
else
{
nodeToDel = list->head;
while (nodeToDel->next)      // Any node other than the head or the tail
{
if (list->compare(todel, nodeToDel->data) == 0)     // If the character exists in the list
{
nodeToDel->next->prev = nodeToDel->prev;
nodeToDel->prev->next = nodeToDel->next;
list->free(nodeToDel->data);
free(nodeToDel);
list->ListSize--;
return TRUE;
}
nodeToDel = nodeToDel->next;       // Moving to the next node
}
}
return FALSE;      // If the character wasn't found in the list return false
}

void printAll(PList list)        // Funciton for printing all items in a set
{
PSet temp;
if (list->head == NULL)      // If the list is empty
printf("nThe list is empty.");
else
{
printf("nThe list is:n");
temp = list->head;
while (temp)       // While there are still nodes left
{
list->print(temp->data);   // Call specific function for printing
temp = temp->next;     // Move to the next node
}
printf("n");
}
}

void deleteSet(PList list)       // Function for deleting a set
{
PSet temp;
if (!(list->head))   // If the list is empty
printf("nThe set is empty.n");
else
{
while (list->head)
{
temp = (list->head);
list->head = list->head->next;   // Moving to the next node
if (list->head != NULL)
list->head->prev = NULL;
list->free((temp->data));     // Call specific function for freeing memory
free(temp);
}
list->ListSize = 0;
list->head = NULL;
list->tail = NULL;
printf("nThe set has been deleted.n");
}
}

主要:

#include "Header.h"
void prnt_string(void* str)       // specific function for printing strings
{
printf("%s  ", (char*)str);
}
void free_string(void* str)     // specific function for freeing memory
{
free((char*)str);
}
int cmp_str(void* s1, void* s2)     // specific function for comparing two strings
{
if (strcmp((char*)s1, (char*)s2) == 0)
return 0;
else if (strcmp((char*)s1, (char*)s2) == 1)
return 1;
else return -1;
}

void prnt_int(void* a)     // Specific function for printing integers
{
printf("%d  ", (int*)a);
}
void free_int(void* a)      // Specific function for freeing integers
{
free(a);
}
int int_comp(void* a, void* b)         // Specific function for comparing integers
{
if ((int*)a == (int*)b)
return 0;
else if ((int*)a > (int*)b)
return 1;
else return -1;
}

int main()
{
char ch, tempstr[31], *str;
int n, option, *num, item;
void *temp;
BOOL status;
PList list;
printf("Choose the type you want to work with:n");
printf("1. Integersn");
printf("2. Stringsn");
printf("Enter input: ");
scanf("%d", &n);
switch (n)
{
case 1:
list = createSet(int_comp, prnt_int, free_int);
do
{
printf("nnChoose the desired action: ('-1' to exit)n");
printf("1. Create a Setn");
printf("2. Add To Setn");
printf("3. Delete From Setn");
printf("4. Find an Item in The Setn");
printf("5. Show The Size of The Setn");
printf("6. Find The Biggest Value In The Setn");
printf("7. Find The Smallest Value In The Setn");
printf("8. Delete The Setn");
printf("Enter input: ");
scanf("%d", &option);
switch (option)
{
case 1:
list = createSet(int_comp, prnt_int, free_int);
printf("nThe Set Has Been Initialized.nn");
break;
case 2:
num = (int*)malloc(sizeof(int));
if (num == NULL)
{
printf("Memory allocation failed!");
deleteSet(list);
return 1;
}
else
{
printf("nEnter a number: ");
scanf("%d", &num);
status = addToSet(list, num);
if (status == TRUE)
{
printf("Number successfully added to set.nn");
printAll(list);
printf("n");
}
else
{
printf("Operation failed!nThe number already exists in the set or memory allocation failed.nn");
deleteSet(list);
return 1;
}
}
break;
case 3:
printf("nEnter number: ");
scanf("%d", &item);
status = deleteFromSet(list, item);
if (status == TRUE)
{
printf("Number successfully deleted.nn");
printAll(list);
}
else
{
printf("Operation failed!nThe number does not exist in the set.nn");
printAll(list);
printf("n");
}
break;
case 4:
printf("nEnter number: ");
scanf("%d", &item);
if (findInSet(list, item) == TRUE)
printf("Item exists in the set.nn");
else printf("Item does not exist in the set or the set is empty.nn");
break;
case 5:
printf("nThe size of the set is %d.nn", setSize(list));
break;
case 6:
temp = findMax(list);
if (temp == NULL) printf("nThe set is empty.nn");
else printf("nThe biggest value in the set is %d.nn", (int*)temp);
break;
case 7:
temp = findMin(list);
if (temp == NULL) printf("nThe set is empty.nn");
else printf("nThe smallest value in the set is %d.nn", (int*)temp);
break;
case 8:
deleteSet(list);
break;
case -1:
printf("nExiting Programnn");
break;
default:
printf("nWrong input!nn");
break;
}
} while (option != -1);
deleteSet(list);
free(list);
break;
case 2:
list = createSet(cmp_str, prnt_string, free_string);
do
{
printf("nnChoose the desired action: ('-1' to exit)n");
printf("1. Create a Setn");
printf("2. Add To Setn");
printf("3. Delete From Setn");
printf("4. Find an Item in The Setn");
printf("5. Show The Size of The Setn");
printf("6. Find The Biggest Value In The Setn");
printf("7. Find The Smallest Value In The Setn");
printf("8. Delete The Setn");
printf("Enter input: ");
scanf("%d", &option);
switch (option)
{
case 1:
list = createSet(cmp_str, prnt_string, free_string);
printf("nThe Set Has Been Initialized.nn");
break;
case 2:
printf("nEnter a string(max of 30 characters):n");
scanf("%s", tempstr);
str = (char*)malloc(strlen(tempstr) + 1 * sizeof(char));
if (str == NULL)
{
printf("Memory allocation failed!nn");
deleteSet(list);
return 1;
}
strcpy(str, tempstr);
status = addToSet(list, str);
if (status == TRUE)
{
printf("String successfully added to set.nn");
printAll(list);
}
else
{
printf("Operation failed!nThe string already exists in the set or memory allocation failed.nn");
deleteSet(list);
return 1;
}
break;
case 3:
printf("nEnter string(max of 30 characters): ");
scanf("%s", tempstr);
status = deleteFromSet(list, tempstr);
if (status == TRUE)
{
printf("String successfully deleted.nn");
printAll(list);
}
else
{
printf("Operation failed!nThe string does not exist in the set.");
printAll(list);
printf("n");
}
break;
case 4:
printf("nEnter string: ");
scanf("%s", tempstr);
if (findInSet(list, tempstr) == TRUE)
printf("Item exists in the set.nn");
else printf("Item does not exist in the set.nn");
break;
case 5:
printf("nThe size of the set is %d.nn", setSize(list));
break;
case 6:
temp = findMax(list);
if (temp == NULL) printf("nThe set is empty.nn");
else
{
printf("nThe biggest value in the set is ");
puts((char*)temp);
printf("n");
}
break;
case 7:
temp = findMin(list);
if (temp == NULL) printf("nThe set is empty.nn");
else
{
printf("nThe smallest value in the set is ");
puts((char*)temp);
printf("n");
}
break;
case 8:
deleteSet(list);
break;
case -1:
printf("nExiting Programnn");
break;
default:
printf("nWrong input!nn");
break;
}
} while (option != -1);
deleteSet(list);
free(list);
break;
default:
printf("nWrong input!nn");
break;
}
getch();
return 0;
}

这是导致问题的函数:

void free_int(void* a)      // Specific function for freeing integers
{
free(a);
}

该代码可以完美地处理字符串,但不能与整数一起使用。 如果有人能指出这个问题,我将不胜感激。 提前谢谢。

您的程序可能会崩溃,因为您正在覆盖指针值:

int* num;                        // [1]
num = (int*)malloc(sizeof(int)); // [2] 
scanf("%d", &num);               // [3] you are changing value of pointer !!
// scanf ("%d", num);            // [4] USE THIS LINE
status = addToSet(list, num);

[1] 指向 int 的声明指针

[2] 内存被分配,它由num指向

[3] 您正在将指针传递到指针作为函数scanf参数,然后您正在修改指针的值(您不是将某个整数值写入num指向的内存区域!因此,当调用free函数时,它会尝试释放无效指针。它是 UB。

[4]scanf("%d",num);使用此行以避免指针值无效的问题

最新更新