0

下面是相关代码:

typedef struct Node_t {
    ListElement data;
    struct Node_t* next;
} Node;

struct List_t {
    Node* head;
    Node* tail;
    Node* current;
    int size;
    CopyListElement copyF;
    FreeListElement freeF;
};

static ListResult initializeNode(List list, ListElement element, Node* newNode){
    printf("\nEntered initializeNode\n");
    if ((list == NULL) || (element == NULL)) return LIST_NULL_ARGUMENT;
    newNode = malloc(sizeof(Node));
    if (newNode == NULL) return LIST_OUT_OF_MEMORY;
    printf("\nWithin initializeNode, before copyF\n");
    ListElement newElement = list->copyF(element);
    printf("\nWithin initializeNode, after copyF\n");
    if (newElement == NULL) return LIST_OUT_OF_MEMORY;
    newNode->data = newElement;
    printf("\nLast line within initializeNode\n");
    return LIST_SUCCESS;
}

List listCreate(CopyListElement copyElement, FreeListElement freeElement){

    //Check if there is a NULL argument.
    if ((copyElement == NULL) || (freeElement == NULL)) return NULL;

    //Check wether there is enough memory.
    List newList = malloc(sizeof(List));
    if (newList == NULL) return NULL;
    //Initialize an empty List.
    newList->head = NULL;
    newList->tail = NULL;
    newList->size = 0;
    newList->current = NULL;
    newList->copyF = copyElement;
    newList->freeF = freeElement;

    return newList;
}

ListResult listInsertFirst(List list, ListElement element){
    printf("\nEntered listInsertFirst\n");
    Node* newNode;
    ListResult result = initializeNode(list, element, newNode);
    printf("\n Node was initialized\n");
    if (result != LIST_SUCCESS) {
        return result;
    }

    printf("\nEntering logistic works within listInsertFirst\n");
    //Finish logistic work within the Node.
    newNode->next = list->head;
    list->head = newNode;
    list->size++;
    printf("\nElement was inserted successfully\n");

printf("\nCheck list->CopyF within listInsertFirst\n");
list->copyF(element);
printf("\nCheck list->CopyF within listInsertFirst: PASSED\n");

    return LIST_SUCCESS;
}

在我正在尝试的主要功能中:

List list = listCreate(&copyInt, &freeInt);

ListResult result;
int el=2;
//ListElement e1;
//ListElement e2;

result = listInsertFirst(list,&el);
printf("\nresult = %d\n", result);

result = listInsertFirst(list,&el);
printf("\nresult = %d\n", result);

编译并运行后,我得到:

进入列表InsertFirst

输入初始化节点

在 initializeNode 中,在 copyF 之前

在 initializeNode 中,在 copyF 之后

initializeNode 中的最后一行

节点已初始化

在 listInsertFirst 中输入后勤工作

元素插入成功

检查列表-> listInsertFirst 中的 CopyF 分段错误:11

由于某种原因,[指向函数] list->copyF 的指针被损坏了[我认为]。

4

2 回答 2

1

我假设这是基于标签的 C 代码,而不是 C++。鉴于您混合了数据定义和实际代码语句,我不希望在 C 中工作,我不能 100% 确定它是真正的 C,在这种情况下,我可能对下面的错误有误。

首先,接口initializeNode()并没有做你可能想要的。你可能想要:

static ListResult initializeNode(List list, ListElement element, Node** newNodep)
{
    Node *newNode = malloc(sizeof(Node));
    if (newNode == NULL) return LIST_OUT_OF_MEMORY;
    ListElement newElement = list->copyF(element);
    if (newElement == NULL) return LIST_OUT_OF_MEMORY;
    newNode->data = newElement;
    *newNodep = newNode;
    return LIST_SUCCESS;
}

这样,您创建的节点就会被传回。

我不知道是什么CopyInt(),但如果它真的是遇到总线错误的功能,那么这个错误initializeNode()就不是你的问题了。但是,在报告崩溃之前,您可能没有看到所有 printfs 的输出。

如果CopyInt()符合我的预期,它会执行以下操作:

ListElement CopyInt(int *val)
{
    ListElement *e = malloc(sizeof(ListElement));
    if (e) 
        e->val = *val;
    return e;
}

如果您弄乱了库函数维护的数据结构,那么您将在这里获得第二次总线错误的唯一方法malloc()。不幸的是,对于这个理论,我没有看到比这里的内存泄漏更糟糕的事情了。

于 2013-04-29T02:11:11.190 回答
0

我猜实际上导致崩溃的错误是这一行:

newNode->next = list->head;

就像@Arlie Stephens 所说的那样 - 代码initializeNode不会做任何事情,因为指针是按值传递的,而实际的指针仍然指向垃圾。因此,当您这样做时,newNode->next = list->head;您基本上是在写入未知地址,并且很可能会出现分段错误。为什么它只发生在第二次通话?不知道,这是未定义的行为。

疯狂的想法 - newNode->next 可能被初始化为 copyF 的地址并尝试写入它会导致您损坏 copyF...尝试打印 newNode->next 的地址和 copyF 的地址。

于 2013-04-29T07:16:06.147 回答