【问题标题】:C / linked list / How can fix the segmentation fault?C/链表/如何修复分段错误?
【发布时间】:2013-12-16 11:54:23
【问题描述】:

当我编译它时,它在

处有分段错误

strcat(arr, cur->texts);dumpTB 函数中。

在main函数中,当dumpTB函数被调用时,应该会打印出来

hello\ngood bye\nworld\n 与我在newTB 函数中输入的相同..

谁能找出问题所在?


我添加了名为 deleteTB(TB tb, int from, int to) 的函数。 我不只是问“你能为我做这个吗?”,我想知道并学习如何解决。 我从昨晚开始尝试..但仍然卡住..

奇怪的是,我在同一行 'strcat(arr, cur->texts)' 遇到了段错误。我试图修改不同的方式和不同的代码..但不知道。

因为我的输入是“hello\ngood bye\nworld\n”..

deleteTB(list , 0 , 1) 这样调用时, // (head node is 0)

printbuffer(list) 应该像这样打印,

POS 0:世界

那么,dumpTB(list) 应该像这样打印,

世界。


由于我不知道这里的规则,我昨晚发布了几乎相同的东西,这让人们很生气。对此感到抱歉。我不只是要求你们这样做。我真的很想学习。


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

#include "textbuffer.h"

#define MAX_TEXT 256

struct textbuffer {
    char *texts;
    int count;
    TB next;
};

TB newTB (char text[]){
    TB newText = malloc(sizeof(struct textbuffer));
    char *cpy = (char *)malloc(MAX_TEXT * sizeof(char));
    TB head = newText; // Store the first node to return

    strcpy(cpy,text);
    newText->count = 0;
    newText->next = NULL;
    int i = 0;
    int j = 0;

    while( cpy[i] != '\0') {
        if( j == 0) {
            head->texts = (char *)malloc(MAX_TEXT * sizeof(char));
        }
        if(cpy[i] == '\n') {
            head->texts[j] = '\0';
            newText->count++;
            head->next = malloc(sizeof(struct textbuffer));
            head = head->next;
            j = 0;
            i++;
        } else {
            head->texts[j++] = cpy[i++];
        }
    }
    head->next = NULL;
    return newText; 
}

void releaseTB (TB tb) {
    TB head = tb;
    TB tmp;

    while(head != NULL) {
        tmp = head;
        head = head->next;
        free(tmp->texts);
        free(tmp);

    }
}

char *dumpTB (TB tb) {
    if(tb == NULL) {
        return NULL;
    }
    TB cur = tb;
    char *arr = (char *)malloc(MAX_TEXT * sizeof(char));

    while(cur != NULL) {
        if(arr == NULL) {
            strcpy(arr,"");
        }
        strcat(arr, cur->texts);
        if(cur->next != NULL) {
            strcat(arr, "\n");
        }
        cur = cur->next;
    }
    return (arr);
}

int linesTB(TB tb) {
    return (tb->count);
}

void printBuffer(TB tb){
    TB curr = tb;
    int i=0;
    while(curr->next != NULL){
        printf("POS %d : %s\n", i++, curr->texts);
        curr = curr->next;
    }
}

void swapTB(TB tb, int pos1, int pos2) {
    if((pos1 < 0) || (pos2 < 0) || (pos1 > linesTB(tb)-1) || (pos2 > linesTB(tb)-1)) {
        printf("**GIVEN LINES ARE OUT OF RANGE**\n");
        abort();
    }
    TB cur = tb;
    TB head = tb;
    int i = 0;

    char *tmp  = (char *)malloc(MAX_TEXT * sizeof(char));
    tb->texts = cur->texts;
    while( i < pos1) {
        cur = cur->next;
        i++;
    }
    strcpy(tmp, cur->texts);
    cur->texts = NULL;
    i=0;
    while( i < pos2) {
        head = head->next;
        i++;
    }
    cur->texts = head->texts;
    head->texts = tmp;
}

void deleteTB(TB tb, int from, int to) {
    if((from < 0) || (to < 0) || (from > linesTB(tb)-1) || (to > linesTB(tb)-1)) {
        printf("**GIVEN LINES ARE OUT OF RANGE**\n");
        abort();
    }
    TB cur = tb;

    int i = 0;

    for(i = 0; i < from; i++) {
        cur = cur->next;
    }
    while( i <= to ) {
        cur->texts = '\0';
        free(cur->texts);
        //free(cur);
        cur = cur->next;
        i++;
    }
}

int main(int argc, char * argv[]) {
    TB list = NULL;
    list = newTB("hello\ngood bye\nworld\n");

    printf("**THERE ARE %d LINES IN TEXTBUFFER**\n", linesTB(list));
    printBuffer(list);
    printf("**Dumping test**\n");
    printf("%s\n",dumpTB(list));

    printf("**Swapping test**\n");
    swapTB(list, 0, 1);
    printBuffer(list);

    printf("**Deleteing test**\n");
    deleteTB(list, 1, 1);
    printBuffer(list);
    printf("%s\n",dumpTB(list));


    releaseTB(list);

    return 0;
}

【问题讨论】:

  • 立即执行调试器。
  • 什么是结核病?和do not cast the return of malloc。并且还使用strdup()...
  • 在 dumpTB 函数中使用 strdup() 作为 arr?!
  • 请不要转换malloc返回的指针。 C中不需要。其实就是把mallocmight do more harm than good的返回值转换成@
  • @BrianSon 不,在 newTB 中使用 strdup 而不是 malloc + strcpy。只需执行texts = strdup。您的函数newTB 不符合唯一目的原则。 newTB应该一个新的TB也应该通过它的换行和东西来切割一个字符串。

标签: c linked-list segmentation-fault


【解决方案1】:

您正在使用strcat 函数。第一个参数是arr,它不是以空值结尾的。 所以在使用strcat之前使用下面的代码

arr[0]='\0';

另外,像这样在循环中检查cur-&gt;next

 while(cur->next != NULL)

此外,由于上述原因,您的releaseTB 将给您segfault。 将循环条件更改为

 while(head->next != NULL) 

编辑

char *dumpTB (TB tb) {
    if(tb == NULL) {
        return NULL;
    }
    TB cur = tb;
    char *arr = (char *)malloc(MAX_TEXT * sizeof(char)); //VS throws error if we wont cast
    arr[0]='\0'; // Null Terminated 
    while(cur->next != NULL) { // changed to cur->next
        if(arr == NULL) {
            strcpy(arr,"");
        }
        strcat(arr, cur->texts);
        if(cur->next != NULL) {
            strcat(arr, "\n");
        }
        cur = cur->next;
    }
    return (arr);
}

void releaseTB (TB tb) {
    TB head = tb;
    TB tmp;

    while(head->next != NULL) { // Changed to head->next
        tmp = head;
        head = head->next;
        free(tmp->texts);
        free(tmp);

    }
}

【讨论】:

  • 我像你说的那样尝试了..但仍然不起作用..顺便说一下,对于循环部分,如果我更改为 while(cur->next != NULL),它不会t打印出任何东西
  • 它似乎有点工作..你怎么能一看到代码就确定哪个部分是错误的..太神奇了
  • 由于我要在上面添加更多功能,想请教一些想法。为了访问每个节点,你会怎么做?因为,我要写一个名为 swapTB(TB tb, int pos1, int pos2) 的函数,它交换节点的 pos1 和 pos2。(头节点在位置 0)。
  • 所以..让输入与上面的代码相同,然后当 swapTB(list,1,2);被调用,那么它应该像“hello”“world”“good bye”一样打印出来。然后再次调用它,swapTB(list,2,1),它应该打印原始输出“hello”“good bye”“world”..
  • 您尝试自己实现逻辑。如果你没有得到,那么你让我知道......快乐编码!
猜你喜欢
  • 2019-06-20
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
  • 2015-07-15
  • 1970-01-01
  • 2021-06-03
相关资源
最近更新 更多