我用C语言创建了一个小程序来测试指向指针的指针。
当我使用函数(第39行)打印列表数据时,在将项目添加到列表后出现错误3221225477。但是,当我注释第39行并从第59行中删除注释时,程序可以工作通常。
如果程序从上到下运行,为什么从操作系统(在这种情况下为Windows)中收到ACCESS_VIOLATION错误?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
struct employee{
int id;
char name[50];
char street[50];
};
typedef struct element* List;
struct element{
struct employee data;
struct element *next;
};
typedef struct element Elem;
List* list_create();
void list_print(List* list);
int list_is_empty(List* list);
int list_add(List* list, struct employee a);
int main(){
List* list = list_create();
struct employee a1;
a1.id = 10;
strcpy(a1.name, "John");
strcpy(a1.street, "Address XYZ");
list_add(list, a1);
//Sleep(5000); small pause, I thinking it might have something to do with thread.
//list_print(list); // *****line--39 *****;
return 0;
}
List* list_create(){
List* li = (List *) malloc(sizeof(List));
if(li != NULL)
*li = NULL;
return li;
}
int list_add(List* list, struct employee emp){
Elem* n1 = (Elem *) malloc(sizeof(Elem));
n1->data = emp;
n1->next = *list;
list = &n1;
list_print(list); // *****line--59 *****;
}
void list_print(List* list){
Elem aux = **list;
printf(" **lista Id: %d\n", aux.data.id);
printf(" **lista name: %s\n", aux.data.name);
printf(" **lista name: %s\n", aux.data.street);
}
答案 0 :(得分:0)
C是按值传递,而不是按引用传递。因此,函数List* list
中的list_add
和List* list
中的main
指的是内存中的两个不同位置(它们最初指向{{ 1}},但是它们是两个不同的指针,其初始值相同,而不是相同的指针):在list_add
中修改变量list
的值不会影响list_add
的值在list
中。
具体来说:
main
中的 list = &n1
仅修改该函数内list_add
的值,即在调用时复制到list
的堆栈帧中的参数值。但是,当您尝试在仍位于list_add
内的第59行上进行打印时,将看到更改后的值,并因此从中打印出指针,并按预期工作。
另一方面,当您尝试在第list_add
行的第39行上打印list
时,main
函数中的变量list
的值没有更改通过main
中第39行之前的赋值list = &n1
进行分配,因为这仅更改了该函数范围内的副本的值。因此,在这种情况下,list_add
尝试打印一个空列表的元素(因为list_print
的值仍然只是list
返回的值,而list_create
是指向{{1}的指针}指针,因此NULL
会解除对Elem aux = **list
的引用,然后尝试解除对list
指针的引用),从而导致无效的内存访问。
那么,此代码中的问题不是列表的打印位置,而是NULL
没有正确更新列表。在解决此问题时,您需要考虑到它只能通过修改作为参数接收的引用值所指向的列表结构来修改列表结构,而不是尝试修改指针本身。如果您确实想修改函数list_add
中list
中指向main
的地址(例如,行list_add
试图做的事情),将需要将指向list = &n1
的指针传递到list
中,而不仅仅是传递指针list_add
本身。
代码本身似乎还有其他问题(例如,list
仅打印一个元素,并且不处理打印空列表,这就是导致错误在这里实际上是无效的内存访问的原因只是在调用list_print
之后错误地使列表为空),但是上述问题是导致此特定问题的原因。