c - 添加到链表时,节点地址一直相互覆盖
问题描述
我正在尝试使用任务列表并将输出通过管道传输到我的代码并解析每一行以创建每个进程的节点。我稍后将通过它们进行过滤,但这还没有在代码中。我在使用LIST
. 我structs
为这个程序实现了 3 个:(LIST
第一个节点的头,最后一个节点的后部和列表中节点数的计数),NODE
(指向PROCESS_INFO
下一个的指针和指针NODE
),PROCESS_INFO
(用于进程名称、PID、内存使用的 4 个字符指针和处理器时间)。我曾经printf
跟踪我的代码,在我将它们添加到链接列表之前,一切似乎都正常工作。每个节点的地址不同,但它似乎总是覆盖列表中的最后一个,而不是将节点的新地址添加到前一个节点的 next* 中。
我很肯定我的算法是正确的,这与我多次使用的算法相同,只是数据不同。我的malloc
函数有动态检查,以防它们出错,并且我已经检查并使用了我的指针,以防我错过了某种取消引用,但是如果我改变任何东西,我会得到错误,所以我认为这些问题不够有趣。
我唯一能想到的问题是所有这些都驻留在函数的循环中(我在某个地方读到堆栈上的指针不记得它们的地址?)。我必须改变什么来解决这个问题?我已将所有内容移至主目录,但没有任何改变。
结构定义:
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_;
}
解决方案
您不会为找到的每个输入字段复制字符串。相反,您将指针保存在path
缓冲区中,每次执行时都会被覆盖fgets
。尝试strdup
使用createPinfo
:
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;
}
}
您可能希望像您一样NULL
检查结果(只要您了解基本概念,我就懒得将其添加到答案中)。strdup
malloc
推荐阅读
- python-3.x - 从 List 中删除 '\n' 并为 Python 中的每个元素创建字符串
- nuxt.js - Workbox 正在预缓存没有修订信息的 URL:/?standalone=true 这通常是不安全的
- linux - 使用 Chef 在 VM 上安装 Azure CLI
- html - 如何在 Markdown 中的 HTML 标签(如 Div)中编写 Latex 公式?
- loops - 在 SPSS 中打开、重新编码和堆叠多个 .csv 文件的宏
- mysql - 具有 INTO OUTFILE 唯一名称的列上的 MySQL 循环语句
- python - open('*.json') 给出“UnicodeDecodeError”
- python - 如何从数据框中的列中选择多个特定值进行绘图
- php - 带有回调的自定义迭代器
- javascript - es6 创建三维数组