【问题标题】:struct * and char * segmentation fault on mallocmalloc 上的 struct * 和 char * 分段错误
【发布时间】:2017-04-19 01:10:48
【问题描述】:

这是我遇到问题的代码:

结构:

struct AtoB
{
    char * strA;
    char * strB;
};

创建结构的函数。从外部文件调用。

AtoB * atob_create(char * a)
{
    struct AtoB * atob = (struct AtoB *)malloc(sizeof(struct AtoB));
    atob->strA = malloc(sizeof((char *)a));
    strcpy(atob->strA, a);

    atob->strB = NULL;
    /* HERE IS PROBLEM NO 1 - SEGMENTATION ERROR OCCURS */
    atob->strB = (char*)malloc(1);
    strB = "\0";

    for(int i = 0; i < (int)strlen(atob->strA); i++)
    {
        char token = atob->strA[i];
        /*
        : 
            append(AtoB * atob, const char a) MAY be called, so atob->strB &
            atob->StrA will not be the same length 
        */
        append(atob, (char)token);
    }
}

char 附加到struct 内的char * 的功能。递归调用。

void append(AtoB * atob, const char a)
{
    size_t sz = strlen(atob->strB);
    /* HERE IS ANOTHER ISSUE:
       1: is this the right way to increase the size of the char * ?
       2: does the struct also need to be realloc here to accommodate? 
    */
    atob->strB = (char*)realloc(atob->strB, sz + 1);
    atob->strB[sz - 1 = a];
    atob->[sz] = "\0";
}

检索最终字符串的函数。从外部文件调用。

char * (AtoB * atob)
{
    return (atob->strB);
}

释放所有已分配内存的功能。从外部文件调用。

void free(AtoB * atob)
{
    free(atob->strA);
    free(atob->strB);
    free(atob);
}

作为一个练习,我需要使用 C 并获取一个字符串的内容,以不同的顺序复制它,或者根据此处不存在问题的标准省略或添加某些字符(因此不包含在代码中)。

我在创建结构或分配第一个 char * strA 时没有问题。当我尝试将内存(甚至一个字符)分配给char * strB 时,就会出现问题。

我收到分段错误。

我如何尝试这样做似乎并不重要,我已经阅读了各种示例并尝试了各种方法,但我无法让它发挥作用。我知道这里有一些内存问题,但我似乎无法解决它。

即使我尝试使用realloc 结构,我也无法将strB 初始化为NULL 以外的任何内容。我需要能够在运行时附加到atob-&gt;strB,字符串的最终长度与atob-&gt;strA 的长度不同。

按照网上的例子,我认为这(作为最简单的初始化)会起作用......但它不起作用:

atob->strB = NULL;
atob->strB = (char*)malloc(1);
atob->strB[0]  "\0";

它与它所在的结构有关吗?

我真的不知道出了什么问题,浪费了很多时间在各种论坛上搜索类似问题,阅读主题并尝试每一个解决方案,我只是试图解决第一个问题。

现在我很困惑,没有时间解决这个问题。如果有人可以告诉我我需要的实际代码,那么我将能够阅读并理解你做了什么以及为什么这是正确的方法。我已经在我不清楚的领域发表了评论,并且非常感谢正确的解决方案。

【问题讨论】:

  • 您不需要将调用类型转换为 malloc。大多数 C++ 程序员都这样做,而且没有必要。
  • 您可以使用调试器并显示崩溃的回溯吗?
  • 为什么不赞成这个?如果问题不清楚,请让操作人员解释更多。
  • 我做了一个示例程序来模拟你的情况。检查[ this ] 一段代码。
  • @sjsam:我听到了,但这已经在 Meta 上讨论了很多,答案是永远不会通过技术手段强迫选民发表评论或原因 - 投票将永远是匿名的。但是,我同意选民自愿提供理由会很好!

标签: c struct char segmentation-fault malloc


【解决方案1】:

这段代码并没有像你想象的那样做:

atob->strA = malloc(sizeof((char *)a));
                    ^ sizeof(char *) is fixed. probably 4 or 8.

所以,如果a 指向更长的字符串,就会出现缓冲区溢出。

如果您使用的是 Linux,最好运行 valgrind 内存检查器,以确保您没有额外的内存处理问题。

调试信息:

编译确保它是使用调试符号编译的(在 gcc 命令中添加 -g)

$ gcc -g -Wall -Werror a.c -o a.out

用 gdb 运行它

$ gdb ./a.out

崩溃后,寻找回溯

(gdb) bt

当你遇到它时,只需查看崩溃的位置并尝试了解原因。

由于我们正在处理内存处理问题,请使用 valgrind:

$ valgrind --leak-check=full ./a.out

查看输出并清除错误。

【讨论】:

  • 对不起,我说过我已经阅读了各种主题、论坛和示例,并最终得到了我所说的代码。它通过各种形式多次改变。为什么最初的 malloc (strA) 有效而第二个 (strB) 无效,即使它们完全相同(即,将 a 复制到每个中)?你能告诉我在 char * strB 中分配 1 个字符的代码应该是什么,然后如何在 append 函数中添加一个字符?
  • 终端显示的错误只是'收到信号11(分段错误)
  • 调试:- 使用 -g 编译程序以允许调试符号
  • make 文件包含 CFLAGS = -std=c99 -c -g。 & 然后编译 gcc $(CFLAGS)。这是输出到终端的唯一错误...
  • 查看我关于调试的其他答案
【解决方案2】:

当您将strB 初始化为空字符串时,您使用:

strB = "\0";

但您应该改用其中一个:

strB = '\0';

或:

strB[0] = '\0'.

字符串文字"\0" 是一个由三个chars 组成的数组:{'\', '0', '\0'}。你在其他地方做同样的事情(这里看起来你漏掉了struct字段的名称):

atob->strB[sz] = "\0";

和(这里我假设您不小心遗漏了赋值运算符):

atob->strB[0] = "\0";

增长字符串的方式存在问题。 strlen() 给出了数组中chars 在NUL 终止符之前的数量,因此如果要添加另一个char,则需要为sz + 2 chars 分配。那么新的char需要放在strB[sz],也就是旧的NUL所在的位置,NUL需要放在字符串的末尾,也就是strB[sz + 1]。 您可以通过将代码更改为:NUL 终止字符串 strB

atob->strB = realloc(atob->strB, sz + 2);
atob->strB[sz] = a;
atob->strB[sz + 1] = '\0';

另外,realloc() 可能返回NULL,从而导致内存泄漏。您应该使用一个临时变量来存储对realloc() 的调用结果:

char *temp = realloc(atob->strB, sz + 2);
if (temp)
    atob->strB = temp;

【讨论】:

  • 是的,大卫对不起,这是一个错字,它是 atob->strB[sz] = "\0"; (我写它不是复制粘贴)。
  • @eyalm - 感谢 sizeof(char *) 已修复。可能是 4 或 8。然后我明白它实际上在分配 strB 之前失败了......
  • @sjsam - 你的例子完全有道理,我现在明白了:在 eyalm 的解释之后,我看到 strA 导致了这个问题,但我仍然无法弄清楚我应该如何获得正确的长度分配。 atob->strA=malloc((l+1)*sizeof(char)); “我明白了!strlen 只是告诉我有多少个 4 字节,而不是需要在内存中分配的实际数量。感谢您的解释,更重要的是阅读我的问题并准确回答我的问题。跨度>
  • @oblong--注意你不需要在malloc中使用sizeof(char)char 是一个字节,malloc() 分配您指定的字节数,因此malloc(1) 为 1 个char 分配空间。实际上,在调用 malloc() 时使用 sizeof(char) 被认为是不好的做法。
  • 嗨@David,谢谢你 - 但是如果你不知道在运行时之前你想要多少空间,你如何分配空间?即在'a'长度未知的情况下, atob->strA=malloc((l+1)*sizeof(char));如果您不使用字符,会执行吗?还是仅适用于字符?即您可以将它用于整数数组吗?
猜你喜欢
  • 2018-10-13
  • 2014-08-12
  • 1970-01-01
  • 1970-01-01
  • 2016-11-05
  • 1970-01-01
  • 2012-07-24
  • 1970-01-01
  • 2014-03-29
相关资源
最近更新 更多