使用与另一个char *相同长度的mallocing char *会导致它成为副本吗?

时间:2016-02-05 20:18:45

标签: c gcc

我目前正在尝试编写一个简单的C程序,该程序使用char *字段创建一个struct,并将其赋值为与argv [1]相同的值。然后我想创建另一个与argv [1]长度相同的char *,但由于某种原因,里面的数据已经包含与argv [1]相同的值。到目前为止,这是我的代码:

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

struct example{
    char *str;
};

struct example* create(char *s){
    struct example *p = (struct example*)malloc(sizeof(struct example));
    char * copy = (char*)malloc(strlen(s));
    strcpy(copy, s);
    p->str = copy;
    free(copy);
    return p;
}

void new_char(struct example * t){
    printf("original: %s\n", t->str);
    char *w = (char *)malloc(strlen(t->str));
    printf("why is this a copy? %s\n", w);
    free(w);
}

void clean(struct example *t){
    free(t);
}

int main(int argc, char **argv){
    struct example * p = create(argv[1]);
    new_char(p);
    clean(p);
    return 0;
}

然后当我使用GCC 6.1编译并运行该程序时,我得到了这个

> gcc -Wall -g -o test test.c
> ./test "test value here"
> original: test value here
> why is this a copy? test value here

4 个答案:

答案 0 :(得分:7)

此代码错误

struct example* create(char *s){
    struct example *p = (struct example*)malloc(sizeof(struct example));
    char * copy = (char*)malloc(strlen(s));
    strcpy(copy, s);
    p->str = copy;
    free(copy);
    return p;
}

首先你需要分配strlen + 1

其次,你无法免费复制&#39;在这里,p-&gt; str指向它,你现在有一个悬空指针。复制和malloc使用strdup http://linux.die.net/man/3/strdup

struct example* create(char *s){
    struct example *p = (struct example*)malloc(sizeof(struct example));
    p->str = strdup(s);
    return p;
}

你获得相同字符串的原因是因为你把你的字符串释放回堆然后当你调用malloc时又把它取回来了,这纯粹是运气,另一次你可能崩溃,得到垃圾,...

答案 1 :(得分:2)

看看这一行:

char * copy = (char*)malloc(strlen(s));
...
p->str = copy;
free(copy);
return p;

你分配一块内存,初始化它,在你的结构中存储一个指针,然后释放它!从那个free()开始,p->str指针指向释放的内存,即不能使用的内存。

接下来会发生什么?你做了另一个:

char *w = (char *)malloc(strlen(t->str));

偶然地,从前面的代码中获取内存,并且由于malloc() 没有以任何方式初始化返回的内存,所以它恰好具有相同的字符串刚刚使用过。

你看到的实际上是垃圾(未初始化的内存)恰好采用了最近使用过的文本的形状。

总结一下,你的代码有三个问题:

  1. 您可以在create()
  2. 中释放您要返回的字符串
  3. 在释放结构之前,不要在clean()中释放字符串。
  4. 你试图打印一个未初始化的内存块,并想知道垃圾意味着什么。

答案 2 :(得分:2)

Hrre是问题所在:

char * copy = (char*)malloc(strlen(s));
strcpy(copy, s);
p->str = copy;
free(copy);

您分配了原始字符串的副本并立即释放它。

char *w = (char *)malloc(strlen(t->str));

此行重用以前释放的内存,这就是为什么你得到相同的内容 - 指针是相同的。

请注意,这种情况非常简单,并且特定于您使用的c库。

答案 3 :(得分:1)

malloc没有初始化它分配的内存。对malloc的第二次调用碰巧分配了第一次调用malloc已经分配的相同内存块(看到它在调用free时已经未分配)。你不能指望这一点。

错误:

  • 你也需要为NUL分配空间。 malloc(strlen(s))应为malloc(strlen(s)+1)
  • 当您打印t->str并尝试查找其长度时,您可能无法访问未分配的内存。你可能并不意味着解除分配它。 free(copy);应移至clean作为free(t->str);
  • 在C ++中转换malloc返回的值是必要的,但在C中是不必要的。

提示:

  • strdupstrlen + malloc + strcpy的便捷快捷方式。
  • 如果你写

    typedef struct { ... } example;
    

    而不是

    struct example { ... };
    

    您可以使用example代替struct example

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

typedef struct {
    char *str;
} example;

example* create(char *s){
    example *p = malloc(sizeof(example));
    p->str = strdup(s);
    return p;
}

void new_char(example * t){
    printf("original: %s\n", t->str);
    char *w = strdup(t->str);
    printf("%s\n", w);  // Prints uninitialized memory.
    free(w);
}

void clean(example *t){
    free(t->str);
    free(t);
}

int main(int argc, char **argv){
    example * p = create(argv[1]);
    new_char(p);
    clean(p);
    return 0;
}