C中的链表丢失头信息

发布于 2024-10-15 12:41:43 字数 1384 浏览 1 评论 0原文

我已经用 C 实现了一个基本链表,作为开发一个简单 shell 的项目的一部分 - 它通过维护 shell 在后台运行的 pid 列表来支持进程的后台运行。代码如下。使用 queue_process(some_pid) 插入第一次工作正常,但随后链接列表的行为就好像列表中从未有任何节点(即“没有现有进程”总是由调试功能打印) )。我已经检查了这个文件以及调用这些函数的文件是否有任何会重置头指针但无济于事的内容。我的链表逻辑中是否遗漏了某些内容?

对queue_process的调用编辑:发生在由shell启动的子进程中,如下所示 /编辑:queue_process(getpid())

谢谢!

    void queue_process(pid_t pid_to_insert)
{
    pmesg(2, "In queue_process.\n");
    if (head == NULL)
    {
        pmesg(3, "No existing processes.\n");
        head = malloc(sizeof(struct xssh_process));
        head->pid = pid_to_insert;
        head->next = NULL;
    }
    else
    {
        pmesg(3, "There are existing processes.\n");
        struct xssh_process *new_process = malloc(sizeof(struct xssh_process));
        new_process->next= head;
        head = new_process;
    }
    print_processes();
}

void print_processes()
{
    pmesg(2, "In print_processes.\n");
    struct xssh_process *at_node = head;
    if (head == NULL) { pmesg(2, "There are currently no background processes.\n"); return; }
    pmesg(2, "Process IDs from head (most recently executed) to tail: %i -> ", at_node->pid);
    while (at_node != NULL)
    {
        pmesg(2, "%i ->", at_node->pid);
        at_node = at_node->next;
    }
    pmesg(3, "Head's pid in print is %i.\n", head->pid);
}

I've implemented a basic linked list in C as part of a project to develop a simple shell - it supports backgrounding of processes by maintaining a list of the pids that the shell has run in the background. Code is below. Inserting with queue_process(some_pid) works fine the first time, but subsequent times the linked list acts as if there are never any nodes in the list (i.e. "No existing processes" is always printed by the debug function). I've checked this file and the file that calls these functions for anything that would reset the head pointer to no avail. Am I missing something in my linked list logic?

The call to queue_process EDIT: happens in the child process started by the shell and looks like this /EDIT: queue_process(getpid())

Thanks!

    void queue_process(pid_t pid_to_insert)
{
    pmesg(2, "In queue_process.\n");
    if (head == NULL)
    {
        pmesg(3, "No existing processes.\n");
        head = malloc(sizeof(struct xssh_process));
        head->pid = pid_to_insert;
        head->next = NULL;
    }
    else
    {
        pmesg(3, "There are existing processes.\n");
        struct xssh_process *new_process = malloc(sizeof(struct xssh_process));
        new_process->next= head;
        head = new_process;
    }
    print_processes();
}

void print_processes()
{
    pmesg(2, "In print_processes.\n");
    struct xssh_process *at_node = head;
    if (head == NULL) { pmesg(2, "There are currently no background processes.\n"); return; }
    pmesg(2, "Process IDs from head (most recently executed) to tail: %i -> ", at_node->pid);
    while (at_node != NULL)
    {
        pmesg(2, "%i ->", at_node->pid);
        at_node = at_node->next;
    }
    pmesg(3, "Head's pid in print is %i.\n", head->pid);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

你的心境我的脸 2024-10-22 12:41:43

这对您遇到的错误没有帮助,但您的代码让我觉得过于复杂:

pmesg(2, "在队列进程中。\n");
如果(头==空)
{
    pmesg(3, "没有现有进程。\n");
    头 = malloc(sizeof(struct xssh_process));
    head->pid = pid_to_insert;
    头->下一个= NULL;
    tail = malloc(sizeof(struct xssh_process));
    尾=头;
}
别的
{
    pmesg(3, "已有进程\n");
    struct xssh_process *new_process = malloc(sizeof(struct xssh_process));
    new_process->next=head;
    头=新进程;
}

这可以简化很多。因为无论如何你都是在列表的头部插入的,所以你不需要为空列表单独的逻辑:

void queue_process(pid_t pid_to_insert) { 
   struct xssh_process *new_process = malloc(sizeof(*new_process));
   new_process->pid = pid_to_insert;
   new_process->next = head;
   head = new_process;
}

同样, print_processes 可以稍微修剪一下:

void print_processes() { 
    struct xssh_process *p;
    for (p=head; p!=NULL; p=p->next)
        printf("%d\n", p->pid);
}

OTOH,链表让我觉得这是一个糟糕的选择 - 考虑到这一点指针至少与 PID 一样大,至少 50% 的内存是指针的开销。

It's no help with the bug you've encountered, but your code strikes me as excessively complex:

pmesg(2, "In queue_process.\n");
if (head == NULL)
{
    pmesg(3, "No existing processes.\n");
    head = malloc(sizeof(struct xssh_process));
    head->pid = pid_to_insert;
    head->next = NULL;
    tail = malloc(sizeof(struct xssh_process));
    tail = head;
}
else
{
    pmesg(3, "There are existing processes.\n");
    struct xssh_process *new_process = malloc(sizeof(struct xssh_process));
    new_process->next= head;
    head = new_process;
}

This can be simplified quite a bit. Since you're inserting at the head of the list anyway, you don't need separate logic for an empty list:

void queue_process(pid_t pid_to_insert) { 
   struct xssh_process *new_process = malloc(sizeof(*new_process));
   new_process->pid = pid_to_insert;
   new_process->next = head;
   head = new_process;
}

Likewise, print_processes can be trimmed down a bit:

void print_processes() { 
    struct xssh_process *p;
    for (p=head; p!=NULL; p=p->next)
        printf("%d\n", p->pid);
}

OTOH, a linked list strikes me as a poor choice -- given that a pointer is at least as large as a PID, at least 50% of your memory is overhead for the pointers.

笨死的猪 2024-10-22 12:41:43

根据您提供的额外信息:

对queue_process的调用发生在
shell启动的子进程
看起来像这样:
queue_process(getpid())

您正在尝试添加到子进程(由 fork() 创建)中的链表,然后检查父进程中的该链表。

这是行不通的 - fork() 创建一个完整的、独立的进程副本。除了显式标记为共享的内存之外,在 fork() 之后对变量进行的修改对于每个进程都是私有的。父级不会看到子级所做的修改,子级也不会看到父级所做的修改。

您应该让父进程调用 queue_process(child_pid),其中 child_pidfork() 的返回值。

Based on your extra information supplied:

The call to queue_process happens in
the child process started by the shell
and looks like this:
queue_process(getpid())

You are trying to add to the linked list in a child process (created by fork()) and then examine that linked list in the parent.

This won't work - fork() creates a complete, independent copy of the process. Except for memory that is explicitly marked as shared, modications to variables made after the fork() are private to each process. The parent won't see modifications made by the child, and the child won't see modifications made by the parent.

You should have the parent call queue_process(child_pid), where child_pid is the return value of fork().

断爱 2024-10-22 12:41:43

当一个变量的值神秘地发生变化时,通常是因为您写入的内容超出了另一个变量的范围,而该变量恰好在内存中相邻。

尝试在调试器的 head 上设置一个观察点,只要该变量发生变化,该观察点就会中断到调试器。这应该可以让您快速找到问题。在gdb 中,命令为watch head

When a variable's value mysteriously changes, it's often because you're writing beyond the bounds of another variable, that happens to be adjacent in memory.

Try setting a watch point in your debugger on head, which will break into the debugger whenever that variable changes. This should let you track the issue down quite quickly. In gdb, the command would be watch head.

差↓一点笑了 2024-10-22 12:41:43

试试这个:

void queue_process(pid_t pid_to_insert)
{
    pmesg(2, "In queue_process.\n");
    if (head == NULL)
    {
        pmesg(3, "No existing processes.\n");
        head = malloc(sizeof(struct xssh_process));
        head->pid = pid_to_insert;
        head->next = NULL;
        // This malloc is not required
        // tail = malloc(sizeof(struct xssh_process));
        tail = head;
    }
    else
    {
        pmesg(3, "There are existing processes.\n");
        struct xssh_process *new_process = malloc(sizeof(struct xssh_process));
        new_process->next= head;
        head = new_process;
    }
    print_processes();
}

void print_processes()
{
    pmesg(2, "In print_processes.\n");
    if (head == NULL) { pmesg(2, "There are currently no background processes.\n"); return; }
    struct xssh_process *at_node = head;

    // While at_node != null
    do
    {
        pmesg(2, "%i ->", at_node->pid);
        at_node = at_node->next;
    }
    while (at_node != null);
    pmesg(3, "Head's pid in print is %i.\n", head->pid);
}

Try this:

void queue_process(pid_t pid_to_insert)
{
    pmesg(2, "In queue_process.\n");
    if (head == NULL)
    {
        pmesg(3, "No existing processes.\n");
        head = malloc(sizeof(struct xssh_process));
        head->pid = pid_to_insert;
        head->next = NULL;
        // This malloc is not required
        // tail = malloc(sizeof(struct xssh_process));
        tail = head;
    }
    else
    {
        pmesg(3, "There are existing processes.\n");
        struct xssh_process *new_process = malloc(sizeof(struct xssh_process));
        new_process->next= head;
        head = new_process;
    }
    print_processes();
}

void print_processes()
{
    pmesg(2, "In print_processes.\n");
    if (head == NULL) { pmesg(2, "There are currently no background processes.\n"); return; }
    struct xssh_process *at_node = head;

    // While at_node != null
    do
    {
        pmesg(2, "%i ->", at_node->pid);
        at_node = at_node->next;
    }
    while (at_node != null);
    pmesg(3, "Head's pid in print is %i.\n", head->pid);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文