struct成员的奇怪值

时间:2013-09-30 02:47:08

标签: c pointers struct

首先是代码。

Shell.c:

/** @file shell.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "log.h"



/**
 * Starting point for shell.
 */
int main() {

    log_t *Log = malloc(sizeof(log_t));
    log_init (Log);
    log_t *temp;
    pid_t pid = getpid();  //get current process id
    char cwd[256];  //allocate array to receive the cwd
    size_t cwd_size = sizeof(cwd); //gets the size of cwd

    char *input_line = NULL;
    size_t line_size = 0;
    ssize_t line_ct;


    for(;;)
    {
        getcwd(cwd, cwd_size); //now we actually get the current working directory
        printf("(pid=%d)%s$ ", pid, cwd);
        line_ct = getline(&input_line, &line_size, stdin);

        if (line_ct <= 0)
        {
            printf("\n");
            break;
        }

        input_line[--line_ct] = '\0'; // remove trailing newline

        if (strcmp(input_line, "exit")==0)
        {
            break;
        }

        if (strncmp(input_line, "cd ", 3) == 0)
        {
            chdir(input_line + 3);
            log_t *new_entry = malloc(sizeof(log_t));
            log_init (new_entry);
            log_t *temp = find_last(Log);
            if (temp == NULL)
            {
                log_push(Log, input_line);
            }

            else 
            {
                log_push(new_entry, input_line);
                temp->next = new_entry;
            }

            continue;

        }

        if (strncmp(input_line, "!#", 2) == 0)
        {
            log_print(Log);
            continue;
        }


    }

    return 0;
}

log.h:

/** @file log.h */

#ifndef __LOG_H_
#define __LOG_H_

typedef struct _log_t {

    char *user_input;
    struct _log_t *next; 

} log_t;

void log_init(log_t *l);
void log_destroy(log_t* l);
void log_push(log_t* l, char *item);
void log_print(log_t *l);
char *log_search(log_t* l, const char *prefix);
log_t *find_last(log_t *first);

#endif

log.c:

/** @file log.c */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "log.h"

/**
 * Initializes the log.
 *
 * You may assuem that:
 * - This function will only be called once per instance of log_t.
 * - This function will be the first function called per instance of log_t.
 * - All pointers will be valid, non-NULL pointer.
 *
 * @returns
 *   The initialized log structure.
 */
void log_init(log_t *l) {


    l->user_input = NULL;
    l->next = NULL;

}

/**
 * Frees all internal memory associated with the log.
 *
 * You may assume that:
 * - This function will be called once per instance of log_t.
 * - This funciton will be the last function called per instance of log_t.
 * - All pointers will be valid, non-NULL pointer.
 *
 * @param l
 *    Pointer to the log data structure to be destoryed.
 */
void log_destroy(log_t* l) {
}

/**
 * Push an item to the log stack.
 *
 *
 * You may assume that:
* - All pointers will be valid, non-NULL pointer.
*
 * @param l
 *    Pointer to the log data structure.
 * @param item
 *    Pointer to a string to be added to the log.
 */
void log_push(log_t* l, char *item) {
    l->user_input = item;
    l->next = NULL;
}


/**
 * Preforms a newest-to-oldest search of log entries for an entry matching a
 * given prefix.
 *
 * This search starts with the most recent entry in the log and
 * compares each entry to determine if the query is a prefix of the log entry.
 * Upon reaching a match, a pointer to that element is returned.  If no match
 * is found, a NULL pointer is returned.
 *
 *
 * You may assume that:
 * - All pointers will be valid, non-NULL pointer.
 *
 * @param l
 *    Pointer to the log data structure.
 * @param prefix
 *    The prefix to test each entry in the log for a match.
 *
 * @returns
 *    The newest entry in the log whose string matches the specified prefix.
 *    If no strings has the specified prefix, NULL is returned.
 */
char *log_search(log_t* l, const char *prefix) {
    return NULL;
}

void log_print(log_t* l)
{
    log_t *temp1 = l;

    while(temp1 != NULL && temp1->user_input != NULL)
    {
        //printf("%s\n", temp1->user_input);
        printf("%p %p %s\n", temp1, temp1->user_input, temp1->user_input);
        temp1 = temp1->next;
    }
}

log_t *find_last(log_t *first)
{
    log_t *temp = first;

    if(temp == NULL || temp->user_input == NULL)
    {
        return NULL;
    }


    while(temp->next != NULL)
    {
        temp = temp->next; 
    }

    return temp;
}

所以我正在尝试创建自己的shell。我正在使用链接列表来创建用户输入的日志。测试我工作的唯一功能 - cd(目录)。然后使用!#,它应该打印用户输入的列表。它使用log的log_print函数

但是出了点问题。日志* user-&gt;输入成员用'!#'填充。他们都共享相同的地址:

collin@ubuntu:~/Desktop/mp3$ ./shell
(pid=14683)/home/collin/Desktop/mp3$ cd test1
(pid=14683)/home/collin/Desktop/mp3$ cd test2
(pid=14683)/home/collin/Desktop/mp3$ cd test3
(pid=14683)/home/collin/Desktop/mp3$ cd test4
(pid=14683)/home/collin/Desktop/mp3$ !#
0x8bbf008 0x8bbf018 !#
0x8bbf0a8 0x8bbf018 !#
0x8bbf0b8 0x8bbf018 !#
0x8bbf0c8 0x8bbf018 !#
(pid=14683)/home/collin/Desktop/mp3$ 

这里发生了什么?这真的很奇怪

2 个答案:

答案 0 :(得分:3)

您没有复制字符串。您只需将输入缓冲区推入日志中,但该缓冲区会不断被覆盖。尝试:

void log_push(log_t* l, char *item) {
    l->user_input = strdup(item);
    l->next = NULL;
}

请注意,当您从日志中删除条目时,您需要稍后使用free清理内存。

答案 1 :(得分:2)

您正在使用char指针作为log_push函数的数据

void log_push(log_t* l, char *item) {
    l->user_input = item;
    l->next = NULL;
}

它只是一个指针,当内容改变时,指针显示改变的内容,即最后一个。指针只显示“input_line”!

尝试生成另一个内存区域或使用strdup作为“paddy”声明。

void log_push(log_t* l, const char* item) {
   l->user_input = (char *) malloc(sizeof(char) * strlen(item));
   strncpy(item, strlen(item), l->user_input);
   ....
   ..
   //or use
   t->user_input = strdup(item);
   ....
}