【问题标题】:Using realloc to concat strings使用 realloc 连接字符串
【发布时间】:2016-10-25 16:13:10
【问题描述】:

我正在尝试连接两个字符串,假设“dest”字符串没有足够的空间来添加另一个,所以我使用动态数组来解决它。

问题是尝试编译代码时出现 mremap_chunk 错误。

我不知道我错过了什么,因为 realloc 调用包含所有正确的参数。


错误:

malloc.c:2869: mremap_chunk: Assertion `((size + offset) & (GLRO (dl_pagesize) - 1)) == 0' failed. 
Aborted (core dumped)

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

char *strcatt(char *s1, char *s2)
{
    int a = strlen(s1);
    int b = strlen(s2);
    int i, size_ab = a+b;

    s1 = (char *) realloc (s1, size_ab*sizeof(char));

    for(i=0; i<b; i++) {
        s1[i+a]=s2[i];
    }

    s1[size_ab]='\0';

    return s1;
}


int main()
{
    char s1[]="12345";
    char s2[]="qwerty";

    strcatt(s1,s2);
    printf("%s\n", s1);

    return 0;
}

【问题讨论】:

  • size_ab = a+b+1替换size_ab = a+b

标签: c arrays realloc strcat


【解决方案1】:

首先,您将非堆内存视为堆内存,不要那样做。

其次,您在计算中没有为终止符包括空间。

这里还有一些要点:

  1. 不要命名以str 开头的函数,这是保留的命名空间。
  2. 缓冲区大小应为size_t,而不是int
  3. Don't cast the return value of malloc() in C
  4. 知道大小后,使用memcpy() 复制内存块。
  5. “右手边”字符串应为const
  6. 处理分配错误的可能性。
  7. 我认为按 sizeof (char) 进行扩展是不好的做法,它始终是 1。

假设逻辑相同,我会这样写:

char * my_strcatt(char *s1, const char *s2)
{
    const size_t a = strlen(s1);
    const size_t b = strlen(s2);
    const size_t size_ab = a + b + 1;

    s1 = realloc(s1, size_ab);

    memcpy(s1 + a, s2, b + 1);

    return s1;
}

【讨论】:

  • 真正的问题不是重新分配自动数组吗?
  • @MohitJain Heh。耶,当然了。我没能读到main()。好收获!
【解决方案2】:

clang 调试器给出了非常清晰的错误描述:

malloc:  error for object 0x7fff6fbb16d6: pointer being realloc'd was not allocated
 set a breakpoint in malloc_error_break to debug

您的两个数组都被初始化为字符串文字。此外,您的函数尝试通过重新分配字符串文字来修改它,这是 C 标准的 wrong,因为您无法重新分配尚未分配的内容,然后将第二个字符串文字的成员复制到“对象" 您打算通过在字符串文字上滥用 realloc() 来进行修改。

如果您动态地定义了第三个字符串,您将在其中将两者的内容相加,则代码将起作用:

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

char *mystrcatt(char *s1, char *s2)
{
    int a = strlen(s1);
    int b = strlen(s2);
    int i, size_ab = a+b;

    char *s3 = malloc (size_ab*sizeof(char)); //sizeof(char) is always 1

    for(i=0; i<a; i++) { //inefficient
        (s3[i])=s1[i];
    }    

    for(i=0; i<b; i++) { //inefficient
        (s3[i+a])=s2[i];
    }

    s3[size_ab]='\0';

    return s3;
}


int main()
{
    char s1[]="12345";
    char s2[]="qwerty";
    char *s3 = mystrcatt(s1,s2);    
    printf("%s\n", s3);
    free(s3);
    return 0;
}

还请注意don't cast malloc() 在 C 中的返回。

【讨论】:

  • gdbgcc 的调试器。 clang 的调试器是什么?
  • lldb 可能是您想要的。这是link。感谢您的意见。
【解决方案3】:

您不能reallocfree 未通过调用malloc 或不是NULL 分配的内存。

来自 7.22.3.5 部分。 C11草案中的realloc函数

realloc 函数释放 ptr 指向的旧对象,并且 返回一个指向新对象的指针,该对象具有由大小指定的size。 新对象的内容应与旧对象的内容相同 释放前的对象,直到新旧对象中的较小者 尺寸。新对象中超出旧对象大小的任何字节 有不确定的值。

所以,s1 = (char *) realloc (s1, size_ab*sizeof(char)); 对于您的输入(自动数组)显然是错误的,千万不要这样做。

还有更多问题可以在调试器的帮助下解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-09
    • 2020-02-27
    • 2020-12-18
    • 1970-01-01
    • 2010-09-12
    • 2010-12-02
    • 2018-10-28
    相关资源
    最近更新 更多