【问题标题】:Why do I get the memory access violation error using pointer to pointer为什么我使用指向指针的指针会出现内存访问冲突错误
【发布时间】:2018-10-03 05:28:51
【问题描述】:

我用 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);

}

【问题讨论】:

  • 您应该做的第一件事是停止类型定义指针。删除这个typedef struct element* List; 并按照element*element** 编写所有内容。也许有些错误会变得更加明显。
  • @n.m.谢谢,我会检查代码并进行更改。

标签: c pointers memory-management


【解决方案1】:

C 是按值传递,而不是按引用传递。因此,函数list_add中的List* listmain中的List* list指的是内存中的两个不同位置(它们最初指向list_add开头的相同位置,但它们是两个不同的指针初始值相同,指针不同):修改list_add 中变量list 的值不会影响mainlist 的值。

具体来说:

list_add 中的list = &amp;n1 仅修改该函数中list 的值,即在调用时复制到list_add 的堆栈帧中的参数值。但是,当您尝试在第 59 行打印它时,仍然在 list_add 内,可以看到更改的值,因此是打印的指针,按您的预期工作。

另一方面,当您尝试在第 39 行的 main 中打印 list 时,main 函数中的变量 list 的值并没有被之前的赋值 list = &amp;n1 更改list_add 中的第 39 行,因为这仅更改了该函数范围内的副本的值。因此,在那种情况下,list_print 尝试打印空列表的元素(因为list 的值仍然是list_create 返回的值,它是指向NULL 指针的指针,所以Elem aux = **list因此取消引用list,然后尝试取消引用NULL 指针),从而导致无效的内存访问。

那么,这段代码中的问题不是列表打印的位置,而是list_add 没有正确更新列表。在解决这个问题时,您需要考虑到它只能通过修改它作为参数接收的引用值所指向的内容来修改列表结构,而不是尝试修改指针本身。如果您确实想从函数list_add 中修改list 指向的main 中的地址(例如list = &amp;n1 行似乎试图做的事情),您需要将指针传递给@ 987654353@ 到 list_add,而不仅仅是指针 list 本身。

代码本身似乎存在其他问题(例如,list_print 仅打印一个元素并且没有处理打印空列表,这就是导致此处错误成为实际无效内存访问的原因,而不仅仅是调用 list_add) 后错误地将列表留空),但上述问题是导致此特定问题的原因。

【讨论】:

  • 我真的不介意按功能复制数据。混乱正是因为它使用了指向指针的指针。至于空列表中的错误列表,我把代码留得更小了。非常感谢你!他的回答准确而富有启发性。
猜你喜欢
  • 1970-01-01
  • 2012-05-27
  • 2020-12-11
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
相关资源
最近更新 更多