C char数组连接内存被转储

时间:2016-04-15 15:47:57

标签: c arrays pointers concatenation dynamic-memory-allocation

我有以下代码:

char * set_number(void)
{
    // char * sname = malloc(sizeof(char) * 18); Original
    char * sname = malloc(sizeof(char) * 19); // After EDIT 1
    memset(sname, '\0', 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;
}

返回:

str : 12345678912345

正如在评论中写的那样,我想将c连接到wnumber

但是,使用strcat()会产生内存转储。

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

我想我仍然误解了这里的逻辑。

2 个答案:

答案 0 :(得分:4)

我认为这个问题是

  • malloc()不返回空初始化的内存块,strcat()期望第一个参数为空终止。
  • 如果要将数组用作 string ,则还需要为null终止符分配内存。

所以,

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

答案 1 :(得分:2)

如果您的字符串以0x00开头,则您要删除该前缀并添加七个字符串。您的方法存在一些问题,其中许多问题已由其他人解决:

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

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

before:    0 x 0 0 1 2 3 4 5 6 7 8 9 1 2 3 4 5 \0
                   |                         |
           +-------+                 +-------+
           |                         |
after      1 2 3 4 5 6 7 8 9 1 2 3 4 5 7 \0
                                       |  |
                                       +--+---- 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++] = '\0';                  // 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;
}