【问题标题】:Seg Fault 11 When Trying to Swap Contents of a String尝试交换字符串内容时的 Seg Fault 11
【发布时间】:2015-02-19 03:08:39
【问题描述】:

所以我正在尝试创建一个文本缓冲区,它将给定文本的行存储到一个列表中。我目前正在编写一个交换函数,但是如果我尝试调整某些行,我会遇到分段错误。

这是我正在使用的当前交换函数:

void swapTB (TB tb, int pos1, int pos2) {

if (tb == NULL) {
    abort();
} 

if (pos1 < 0 || pos1>tb->size || pos2<0 || pos2>tb->size) {
    printf("error: lines are out of range!\n");
    abort();
}

link line1 = findLine(tb, pos1);
link line2 = findLine(tb, pos2);

char *temp = (char *)malloc((strlen(line1->line) + 1) * sizeof(char));
strcpy(temp,line1->line);
strcpy(line1->line, line2->line);
strcpy(line2->line,temp);

free(temp);

}

如果我尝试输入此文本:

char text[] = "0. She walks in beauty, like the night\n"
              "1. Of cloudless climes and starry skies;\n"
              "2. And all that’s best of dark and bright\n"
              "3. Meet in her aspect and her eyes;\n"
              "4. Thus mellowed to that tender light\n"
              "5. Which heaven to gaudy day denies.\n"
              "6. One shade the more, one ray the less,\n"
              "7. Had half impaired the nameless grace\n"
              "8. Which waves in every raven tress,\n"
              "9. Or softly lightens o’er her face;\n"
              "10. Where thoughts serenely sweet express,\n";

并进行以下交换:

swapTB(tb, 4, 7);
swapTB(tb, 2, 9);
swapTB(tb, 2, 10);

它工作正常,我得到这个输出:

0. She walks in beauty, like the night
1. Of cloudless climes and starry skies;
10. Where thoughts serenely sweet express,
3. Meet in her aspect and her eyes;
7. Had half impaired the nameless grace
5. Which heaven to gaudy day denies.
6. One shade the more, one ray the less,
4. Thus mellowed to that tender light
8. Which waves in every raven tress,
2. And all that’s best of dark and bright
9. Or softly lightens o’er her face;

但是,如果我稍微改变一下文字,比如缩短第 9 行:

char text[] = "0. She walks in beauty, like the night\n"
              "1. Of cloudless climes and starry skies;\n"
              "2. And all that’s best of dark and bright\n"
              "3. Meet in her aspect and her eyes;\n"
              "4. Thus mellowed to that tender light\n"
              "5. Which heaven to gaudy day denies.\n"
              "6. One shade the more, one ray the less,\n"
              "7. Had half impaired the nameless grace\n"
              "8. Which waves in every raven tress,\n"
              "9. Or softly lightens o’er\n"
              "10. Where thoughts serenely sweet express,\n";

我得到一个分段错误 11。

这种情况一直在发生,有时它工作正常,有时它会出现分段错误,有时它会运行但最终输出有重复 - 这一切都取决于我提供函数的文本。

顺便说一句,文本被存储在这样的结构中:

typedef struct textNode *link;

struct textNode {
    char *line;
    link next;
};

struct textbuffer{
    link head;
    link last;
    int size;
}; 

编辑:

分配换行符的函数:

link newLine(char text[], int start, int i) {

    link newLine = malloc(sizeof(*newLine));
    assert(newLine != NULL);

    newLine->line = extract(text, start, i);
    //printf("newline is %s\n", newLine->line);
    newLine->next = NULL;

    return newLine;

}

提取函数

char* extract(const char* src, int start, int end) {

    return strndup(src + start, (end - start)+1);
}

查找线的功能

link findLine(TB tb, int pos) {

    link curr = tb->head;
    int index = 0;

    while (index != pos) {
        curr = curr->next;
        index++;
    }

    return curr;
}

【问题讨论】:

  • 如何初始化line 成员?发布该代码。
  • @iharob 我用人们在下面发布的指针解决方案修复了它!但如果你仍然好奇,我使用了 strndup 和一个 while 循环,它在换行符之后索引每个地方
  • 那你现在有内存泄漏。
  • @iharob 后指针解决,怎么回事?
  • 因为你必须freestrdup的返回值。可以发一下findLine函数吗?

标签: c string char segmentation-fault swap


【解决方案1】:

问题似乎是您有时将较长字符串中的数据写入先前为较短字符串分配的空间。进行交换的代码,即这五行有问题:

char *temp = malloc(strlen(line1->line) + 1); // No need to cast or multiply by sizeof(char)
strcpy(temp,line1->line);
strcpy(line1->line, line2->line);
strcpy(line2->line,temp);
free(temp);

您的代码确保temp 中有足够的空间用于来自line1-&gt;line 的数据,但假设line2-&gt;line 中有足够的空间用于来自temp 的数据并且还有足够的空间line1-&gt;line 中所有line2-&gt;line 字符的空格。

要解决这个问题,要么重新分配指针,要么进行指针交换而不是交换内容,即

char *temp = line1->line;
line1->line = line2->line;
line2->line = temp;

【讨论】:

  • 这是个好建议,尤其是do pointer swap instead of swapping the content 部分。这就是这样做的方法。
【解决方案2】:

您必须正确编写交换操作。而不是这段代码

char *temp = (char *)malloc((strlen(line1->line) + 1) * sizeof(char));
strcpy(temp,line1->line);
strcpy(line1->line, line2->line);
strcpy(line2->line,temp);

应该有

char *temp  = line1->line;
lin1->line  = line2->line;
line2->line = temp;

如您所见,无需复制字符串本身。交换指针就足够了。

考虑到将数据成员size 定义为具有int 类型没有任何意义,然后每次检查它是否小于零。如果将 size 定义为具有 size_t 类型会更好

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多