Связанный список в C теряет голову информации - PullRequest
0 голосов
/ 01 февраля 2011

Я реализовал базовый связанный список в C как часть проекта по разработке простой оболочки - он поддерживает фоновое управление процессами, поддерживая список pids, которые оболочка выполняла в фоновом режиме. Код ниже. Вставка с queue_process(some_pid) отлично работает в первый раз, но в последующие моменты связанный список действует так, как будто в списке никогда нет узлов (т.е. функция «Нет существующих процессов» всегда печатается функцией отладки). Я проверил этот файл и файл, который вызывает эти функции для всего, что могло бы сбросить указатель головы безрезультатно. Я что-то упустил в логике связанного списка?

Вызов queue_process EDIT: происходит в дочернем процессе, запущенном оболочкой, и выглядит следующим образом / EDIT: 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);
}

Ответы [ 4 ]

3 голосов
/ 01 февраля 2011

Это не поможет с ошибкой, с которой вы столкнулись, но ваш код кажется мне слишком сложным:

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;
}

Это можно немного упростить. Так как вы вставляете заголовок списка в любом случае, вам не нужна отдельная логика для пустого списка:

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% вашей памяти занимают указатели.

1 голос
/ 07 февраля 2011

На основании предоставленной вами дополнительной информации:

Вызов queue_process происходит в дочернем процессе, запущенном оболочкой, и выглядит так: queue_process(getpid())

пытаются добавить в связанный список в дочернем процессе (созданном fork()), а затем изучить этот связанный список в родительском процессе.

Это не сработает - fork() создает полный, независимая копия процесса.За исключением памяти, которая явно помечена как общая, изменения переменных, сделанные после fork(), являются частными для каждого процесса.Родитель не увидит изменения, сделанные ребенком, и ребенок не увидит изменения, сделанные ребенком.

Вы должны иметь родительский вызов queue_process(child_pid), где child_pid - возвращаемое значениеfork().

1 голос
/ 01 февраля 2011

Когда значение переменной таинственным образом изменяется, это часто происходит потому, что вы пишете за пределами другой переменной, которая оказывается смежной в памяти.

Попробуйте установить точку наблюдения в отладчике на head, которая будет зависать в отладчике при изменении этой переменной. Это должно позволить вам выследить проблему довольно быстро. В gdb команда будет watch head.

0 голосов
/ 01 февраля 2011

Попробуйте это:

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...