【问题标题】:Address of nodes keep overwriting each other when being added to linked list添加到链表时,节点地址一直相互覆盖
【发布时间】:2020-01-22 07:28:13
【问题描述】:

我正在尝试使用任务列表并将输出通过管道传输到我的代码并解析每一行以创建每个进程的节点。我稍后将通过它们进行过滤,但这还没有在代码中。我遇到了LIST 的问题。我已经为这个程序实现了 3 个structsLIST(第一个节点的头部,最后一个节点的尾部和列表中节点数的计数),NODE(指向PROCESS_INFO 的指针和指向下一个NODE 的指针), PROCESS_INFO (进程名称、PID、内存使用和 cputime 的 4 个字符指针)。我已经使用printf 来跟踪我的代码,并且在我将它们添加到链接列表之前,一切似乎都正常工作。每个节点的地址不同,但似乎总是覆盖列表中的最后一个,而不是将节点的新地址添加到前一个节点的 next* 中。

我很肯定我的算法是正确的,这与我多次使用的算法相同,只是数据不同。我的malloc 函数有动态检查,以防它们出错,我已经检查并使用了我的指针,以防我错过了某种取消引用,但如果我改变任何东西,我会得到错误,所以我认为这些问题不够有趣.

我唯一能想到的问题是所有这些都驻留在函数的循环中(我在某个地方读到堆栈上的指针不记得它们的地址?)。我必须改变什么来解决这个问题?我已将所有内容移至 main 但没有任何改变。

结构定义:

typedef struct processInfo{
    char *pName;
    char *processId;
    char *memUsage;
    char *cpuTime;
}PROCESS_INFO;

typedef struct node{
    PROCESS_INFO* data;
    struct node* next;
}NODE;

typedef struct li{
    int num;
    NODE* head;
    NODE* rear;
}LIST;

主要功能:

int main()
{
    LIST* list;
    list = buildList();
    printList(list);
}

列出函数:

//function that creates a new list and returns it as null
LIST* createList()
{
    LIST* newListPtr;
    newListPtr = (LIST*)malloc(sizeof(LIST));

    if (newListPtr)
    {
        newListPtr->num = 0;
        newListPtr->head = NULL;
        newListPtr->rear = NULL;
    }
    return newListPtr;
}

//function that creates the struct for the information of the process
PROCESS_INFO* createPinfo(char* name, char* pid, char* kb, char* cTime)
{
    PROCESS_INFO* pInfoPtr;
    pInfoPtr = (PROCESS_INFO*)malloc(sizeof(PROCESS_INFO));

    if (pInfoPtr)
    {
        pInfoPtr->pName = name;
        pInfoPtr->processId = pid;
        pInfoPtr->memUsage = kb;
        pInfoPtr->cpuTime = cTime;
    }
    return pInfoPtr;
}

//function to create new node and set its data
NODE* createNode(PROCESS_INFO* dataPtr)
{
    NODE* nodePtr;
    nodePtr = (NODE*)malloc(sizeof(NODE));

    if (nodePtr)
    {
        nodePtr->data = dataPtr;
        nodePtr->next = NULL;
    }
    return nodePtr;
}

//Get process information node via the path
PROCESS_INFO* parseInfoFromPath (char str[])
{
    char *pName;
    char *processId;
    char *memUsage;
    char *time;
    char *parse;

    parse = strtok(str, " ");
    pName = parse;

    parse = strtok(NULL, " ");
    processId = parse;

    parse = strtok(NULL, " "); //Console
    parse = strtok(NULL, " "); //session
    parse = strtok(NULL, " "); //memory
    memUsage = parse;

    parse = strtok(NULL, " ");
    parse = strtok(NULL, " ");
    parse = strtok(NULL, " ");
    parse = strtok(NULL, " "); //CPUTIME
    time = parse;

    PROCESS_INFO* pInfoPtr;
    pInfoPtr = createPinfo(pName, processId, memUsage, time); 

    return pInfoPtr;
}

BuildList() 函数,我似乎遇到了语义错误:

LIST* buildList()
{
    FILE *fp;
    char path[PATH_MAX];

    fp = popen("tasklist /v /fi \"STATUS eq running\" /nh ", "r");
    if (fp == NULL)
    {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return;
    }

    LIST* list_;
    PROCESS_INFO* p;
    NODE* n;
    list_ = createList();

    while (fgets(path, PATH_MAX, fp) != NULL)
    {
        if (path != NULL)
       {
            //create the process info struct
            p = parseInfoFromPath(path);

            //create the node
            n = createNode(p);

            //add node to list
            //if empty list set as head
            if (list_->head == NULL){
                list_->head = n;
            }
            //otherwise set last->next to point to the new node
            else {
                list_->rear->next = n;
            }

            //rear points to last node
            list_->rear = n;
            (list_->num)++;

        }

    }
    //They always print out the same data!!!!
    printf("\nIn Loop: Head Node name: %s", list_->head->data->pName); 
    printf("\t\tIn Loop: Read Node name: %s", list_->rear->data->pName);
    return list_;
}

【问题讨论】:

标签: c memory linked-list


【解决方案1】:

您不会为找到的每个输入字段复制字符串。相反,您将指针指向您的path 缓冲区,每次执行fgets 时都会覆盖该缓冲区。尝试在createPinfo 中使用strdup

PROCESS_INFO* createPinfo(char* name, char* pid, char* kb, char* cTime)
{
    PROCESS_INFO* pInfoPtr;
    pInfoPtr = (PROCESS_INFO*)malloc(sizeof(PROCESS_INFO));

    if (pInfoPtr)
    {
        pInfoPtr->pName = strdup(name);
        pInfoPtr->processId = strdup(pid);
        pInfoPtr->memUsage = strdup(kb);
        pInfoPtr->cpuTime = strdup(cTime);
    }
    return pInfoPtr;
}

另外,由于strdup 分配堆内存,所以不要忘记添加一个函数来释放内存,并在每次从列表中删除某些内容时调用它。例如:

void destroyPinfo(PROCESS_INFO* pInfoPtr)
{
    if (pInfoPtr)
    {
        free(pInfoPtr->pName);
        pInfoPtr->pName = NULL;

        free(pInfoPtr->processId);
        pInfoPtr->processId = NULL;

        free(pInfoPtr->memUsage);
        pInfoPtr->memUsage = NULL;

        free(pInfoPtr->cpuTime);
        pInfoPtr->cpuTime = NULL;
    }
}

您可能希望NULLmalloc 一样检查strdup 的结果(不过,我懒得将此添加到答案中,只要您了解基本概念)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    • 1970-01-01
    • 2013-12-09
    • 2022-08-17
    相关资源
    最近更新 更多