【问题标题】:Run-time crash in C program mimicking 'strings' UNIX command模仿“字符串”UNIX命令的C程序运行时崩溃
【发布时间】:2013-10-23 13:40:55
【问题描述】:

原程序跟进:Segmentation fault (core dumped) in C byte reader

我的程序应该有点模仿(以原始方式),但目前无法正常工作。

我已经为此工作了很长时间,之前我遇到了分段错误(核心转储),原因是我用作 first_node 的未初始化节点,或者因为我之前使用的方式feof() 而不是 fread(...) != 0。我已经实现了昨晚提出的两个建议,但现在我比以前更加茫然。我不太确定这个错误意味着什么,更不用说为什么我得到它了。以下是我的源代码:

#include <stdio.h>
#include <stdlib.h>

struct node{
    char ANSII;
    struct node *next_node;
};

void clear_list(struct node *first_node);
void print(struct node *first_node);
int counter(struct node *first_node);
void append(char temp, struct node *first_node);


int main(int argc, char **argv){
    FILE *f = NULL;
    struct node header;
    char temp;

    if(argc != 2){ /* argv[0] = name of the program, argv[1] = file to open */
        printf("usage: %s filename:", argv[0]);
    }

    f = fopen(argv[1], "rb");

    if(f == 0){ /* check for successful read */
         printf("Could not open file.\n");
    }

    while(!feof(f)){
        fread(&temp, sizeof(1), 1, f);
        if(temp >= 32 && temp <= 128){ /* If it falls between the bounds of printable     characters. */
            append(temp, &header); //Builds the string
        }else{
            if(counter(&header) > 3){
                print(&header);
            }
            clear_list(&header);
        }
    }
    return 0;
}
void clear_list(struct node *first_node){
    struct node *conductor;
    while(first_node != NULL){
        conductor = first_node;
        while(conductor->next_node != NULL){
            conductor = conductor->next_node;
        }
        free(conductor);
    }
}
void print(struct node *first_node){
    struct node *conductor = first_node;
    while(conductor != 0){
        printf("%s", conductor->ANSII);
        conductor = conductor->next_node;
    }
    printf("\n");
}
int counter(struct node *first_node){
    struct node *conductor = first_node;
    int counter = 0;
    while(conductor != 0){
        conductor = conductor->next_node;
        counter++;
    }
    return counter;
}
void append(char temp, struct node *first_node){
    struct node *conductor = first_node;
    while(conductor->next_node != 0){
        conductor = conductor->next_node;
    }
    conductor->next_node = malloc(sizeof(conductor->next_node));
    if(conductor->next_node == 0){
        printf("Memory allocation failed!");
        return;
    }
    conductor = conductor->next_node;
    conductor->ANSII = temp;
}

到目前为止,我尝试实现答案,但现在我得到了以下运行时崩溃,而不是分段错误:

*** glibc detected *** ./mystrings: double free or corruption (fasttop): 0x0000000000601250   ***
======= Backtrace: =========
/lib64/libc.so.6[0x3886a75916]
./mystrings[0x400798]
./mystrings[0x40072f]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x3886a1ecdd]
./mystrings[0x4005b9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 00:1b 1921384528                         /afs/pitt.edu/home/n/a/nap54/private/cs449/project2/mystrings
00600000-00601000 rw-p 00000000 00:1b 1921384528                              /afs/pitt.edu/home/n/a/nap54/private/cs449/project2/mystrings
00601000-00622000 rw-p 00000000 00:00 0                                  [heap]
3886600000-3886620000 r-xp 00000000 fd:00 180                            /lib64/ld-2.12.so
388681f000-3886820000 r--p 0001f000 fd:00 180                            /lib64/ld-2.12.so
3886820000-3886821000 rw-p 00020000 fd:00 180                            /lib64/ld-2.12.so
3886821000-3886822000 rw-p 00000000 00:00 0
3886a00000-3886b89000 r-xp 00000000 fd:00 183                            /lib64/libc-2.12.so
3886b89000-3886d89000 ---p 00189000 fd:00 183                            /lib64/libc-2.12.so
3886d89000-3886d8d000 r--p 00189000 fd:00 183                            /lib64/libc-2.12.so
3886d8d000-3886d8e000 rw-p 0018d000 fd:00 183                            /lib64/libc-   2.12.so
3886d8e000-3886d93000 rw-p 00000000 00:00 0
388d200000-388d216000 r-xp 00000000 fd:00 6639                           /lib64/libgcc_s-4.4.6-20120305.so.1
388d216000-388d415000 ---p 00016000 fd:00 6639                           /lib64/libgcc_s-  4.4.6-20120305.so.1
388d415000-388d416000 rw-p 00015000 fd:00 6639                           /lib64/libgcc_s-    4.4.6-20120305.so.1
7ffff7fd5000-7ffff7fd8000 rw-p 00000000 00:00 0
7ffff7ffb000-7ffff7ffe000 rw-p 00000000 00:00 0
7ffff7ffe000-7ffff7fff000 r-xp 00000000 00:00 0                          [vdso]
7ffffffea000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted (core dumped)

现在我完全迷路了。有人可以(更多?)洞察力吗?谢谢你们的帮助,我昨晚没睡多少觉,这个项目(连同更重要的第二部分)今晚午夜到期……我知道我只是在粘贴我的代码并说“有它”,但我真的不知道从哪里开始,因为这是我第一次遇到这样的崩溃。

【问题讨论】:

标签: c memory linked-list


【解决方案1】:

您的clear_list 函数释放列表的尾部,然后重复。一旦它到达只剩下一个节点的地步,它就会反复尝试释放first_nodeclear_list 可以更简单地写成

void clear_list(struct node *first_node){
    struct node *ptr = first_node;
    struct node *next;
    while (ptr != NULL) {
        next = ptr->next_node;
        free(ptr);
        ptr = next;
    }
}

Grijesh Chauhan 最初指出的另一个问题是这条线

printf("%s", conductor->ANSII);

错了。 conductor-&gt;ANSII 具有 char 类型,因此您应该使用 %c 格式说明符来打印其值。

【讨论】:

  • 我没有注意到这个问题,也添加了打印问题(删除了我的答案)。我今天的投票限制已达到,因此请考虑您的两个答案:)
  • @GrijeshChauhan 您是否建议我将您发现的 printf 格式说明符错误添加到我的答案中?我现在已经做到了。如果这不是您想要的,请随时编辑我的答案。
  • @simcon 是的,这就是我希望您在答案中添加的内容。这是print(){..} 函数中的另一个问题。我认为 OP 在他发布问题时并没有意识到这一点。但这不是他问的问题,所以我删除了我的答案。
  • 非常感谢——这也是有道理的,而且这是一个巧妙的方法,使用两个指针来简化和更有效地清除链表!
【解决方案2】:

你真的应该学习如何使用像 gdb 或其他的调试器。

一个明显的问题是您没有初始化header 结构中的next 字段。所以当你去追加时,它会开始遍历它,谁知道它最终会在哪里结束(不要假设字段初始化为 0)

【讨论】:

  • 感谢您的帮助。我忘记了我从昨晚(我从中提取代码的地方)更新了我的代码以初始化下一个字段。不过,我感谢您的帮助!
【解决方案3】:

你用了两次sizeof,都错了。

sizeof(1)int 的大小,因为 1 是 int 常量。最有可能是 4,典型的 8 位字节和 32 位 ints。所以你的fread 正试图将 4 个字节读入一个字符。这很糟糕。

在另一个中,您几乎已经使用了推荐的安全sizeof 成语malloc

p = malloc(sizeof *p);

但你忘记了*。所以你分配了足够的空间来保存指向结构的指针,不足以保存结构。

conductor->next_node = malloc(sizeof(*conductor->next_node));

【讨论】:

  • 完全正确 - 1 只是一个错字/逻辑错误,一定是由于粗心造成的。但我什至没有意识到我为新结构错误地执行了 malloc,我感谢您的澄清和推理。这对我的理解很有帮助。
猜你喜欢
  • 2020-07-25
  • 2017-06-21
  • 1970-01-01
  • 2021-01-08
  • 1970-01-01
  • 2018-01-26
  • 2016-02-03
  • 1970-01-01
相关资源
最近更新 更多