C 字符数组串联内存转储

C char array concatenation memory dumped

我有以下代码:

char * set_number(void)
{
    // char * sname = malloc(sizeof(char) * 18); Original
    char * sname = malloc(sizeof(char) * 19); // After EDIT 1
    memset(sname, '[=10=]', 19);                  // After EDIT 1
    strcat(sname, "0x0012345678912345");
    return sname;
}

char * get_number(void)
{
    char * rnumber = set_number();
    return rnumber;
}

char * work_with_number(void)
{
    int i = 7;
    char * wnumber = get_number();
    if(strstr(wnumber, "0x00") != NULL)
    {
        wnumber += 4;
        char c = i + '0';
        // Would like to concatene c at the end of wnumber here
    }
    return wnumber;
}

int main(int argc, char **argv)
{
    char * str = work_with_number();
    fprintf(stdout, "str : %s\n", str);
    return 0;
}

returns :

str : 12345678912345

正如评论中所写,我想将 c 连接成 wnumber

但是,使用 strcat() 会导致内存转储。

此外,内存需要释放到主函数中,不是吗?

我想我还是误解了这里的逻辑。

在我看来,问题是

  • malloc() 不会 return 空初始化的内存块并且 strcat() 期望第一个参数是空终止的。
  • 如果要将数组用作 string.
  • ,还需要为空终止符分配内存

所以,

  1. 在为 sname.
  2. 分配内存时,分配 space 用于保存空终止符
  3. 使用strcpy()将字符串复制到sname。否则,如果你想继续使用strcat(),你可以调用calloc()其中return的0填充内存。
  4. 您只能在 return 由 malloc() 和家人编辑的原始指针上调用 free()。如果您打算移动实际指针,则需要在某处保留原始指针的副本,以便稍后传递给 free()

如果您的字符串以 0x00 开头,您希望删除该前缀并附加一个 7。你的方法有几个问题,其中许多问题已经被其他人解决了:

  • 您必须保留从 malloc 收到的指针,以便稍后 free 内存。
  • 您的字符串末尾没有空间来连接任何内容。
  • strstr 在字符串中的任意位置查找搜索字符串,但您想测试 0x00 是否在开头。为此使用 strncmp
  • strcat 连接到以零结尾的字符串,但是先将内存归零然后 strcatting 是浪费的。 strcpy 直接到字符串。

另一种方法是将字符串的其余部分移到前面。这将在末尾留下四个字符,您可以使用它们来附加内容,但不能超过您删除的内容,当然:

before:    0 x 0 0 1 2 3 4 5 6 7 8 9 1 2 3 4 5 [=10=]
                   |                         |
           +-------+                 +-------+
           |                         |
after      1 2 3 4 5 6 7 8 9 1 2 3 4 5 7 [=10=]
                                       |  |
                                       +--+---- new

你可以为此写一个循环,但标准库中也有两个函数:memcpy,要求缓冲区不重叠,memmove,可以处理重叠缓冲区。你需要 memmove.

所以:

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

char *get_number(void)
{
    char *sname = malloc(19);

    if (sname) strcpy(sname, "0x0012345678912345");
    return sname;
}

char *work_with_number(void)
{
    char *wnumber = get_number();

    if(strncmp(wnumber, "0x00", 4) == 0) {
        size_t len = strlen(wnumber + 4);       // length of rest of str

        memmove(wnumber, wnumber + 4, len);     // move rest to front
        wnumber[len++] = '7';                   // append digit seven
        wnumber[len++] = '[=11=]';                  // append null terminator!
    }

    return wnumber;
}

int main(int argc, char **argv)
{
    char *str = work_with_number();

    fprintf(stdout, "str : %s\n", str);         // user str
    free(str);                                  // free it after use

    return 0;
}