Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将字符*与另一个字符*长度相同的Mallocing字符*会导致它成为副本吗?_C_Gcc - Fatal编程技术网

将字符*与另一个字符*长度相同的Mallocing字符*会导致它成为副本吗?

将字符*与另一个字符*长度相同的Mallocing字符*会导致它成为副本吗?,c,gcc,C,Gcc,我目前正在尝试编写一个简单的C程序,该程序创建一个带有char*字段的结构,并将其赋值为与argv[1]相同的值。然后我想创建另一个与argv[1]长度相同的char*,但由于某些原因,其中的数据已经包含与argv[1]相同的值。以下是我目前的代码: #include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> struct example{ c

我目前正在尝试编写一个简单的C程序,该程序创建一个带有char*字段的结构,并将其赋值为与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;
}
这个代码是错误的

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

第二,你不能在这里释放“复制”,p->str指向它,你现在有一个悬空的指针。要复制和malloc,请使用strdup

获得相同字符串的原因是,您将字符串释放回堆,然后在调用malloc时再次获得字符串,这纯粹是运气,下次您可能会崩溃,得到垃圾,…

请看以下几行:

char * copy = (char*)malloc(strlen(s));
...
p->str = copy;
free(copy);
return p;
您可以分配一块内存,初始化它,在结构中存储指向它的指针,然后释放它!从上的
free()
开始,指针指向已释放的内存,即不能使用的内存

接下来会发生什么?你可以做另一件事:

char *w = (char *)malloc(strlen(t->str));
它碰巧从前面的代码中释放了get memory,而且由于
malloc()
没有以任何方式初始化返回的内存,因此它恰好与您刚才使用的字符串相同

您看到的实际上是垃圾(未初始化的内存),它恰好是最近使用的文本的形状

总而言之,您的代码有三个问题:

  • 释放在
    create()中返回的字符串
  • 在释放结构之前,不要在
    clean()
    中释放字符串
  • 您试图打印未初始化的内存块,并想知道垃圾意味着什么

  • malloc
    不会初始化它分配的内存。对
    malloc
    的第二次调用恰巧分配了第一次调用
    malloc
    分配的相同内存块(正如调用
    free
    时它已变得未分配一样)。你不能指望这一点

    错误:

    • 您还需要为NUL分配空间<代码>malloc(strlen)应该是
      malloc(strlen)+1
    • 当您打印
      t->str
      和试图查找其长度时,您可能无法访问未分配的内存。你可能不是有意要取消分配的<代码>免费(副本)应移动到
      clean
      as
      free(t->str)
    • 在C++中强制转换由<代码> MALLC/<代码>返回的值,但在C.中不需要
    小贴士:

    • strdup
      strlen
      +
      malloc
      +
      strcpy
      的便捷快捷方式
    • 如果你写信

      typedef struct { ... } example;
      
      而不是

      struct example { ... };
      
      您可以使用
      example
      而不是
      struct example


    #包括
    #包括
    #包括
    #包括
    类型定义结构{
    char*str;
    }榜样;
    示例*创建(字符*s){
    示例*p=malloc(sizeof(示例));
    p->str=strdup(s);
    返回p;
    }
    作废新字符(示例*t){
    printf(“原件:%s\n”,t->str);
    char*w=strdup(t->str);
    printf(“%s\n”,w);//打印未初始化的内存。
    免费(w);
    }
    空洞清理(示例*t){
    自由(t->str);
    自由(t);
    }
    int main(int argc,字符**argv){
    示例*p=create(argv[1]);
    新(p),;
    清洁(p);
    返回0;
    }
    
    Hrre是问题所在:

    char * copy = (char*)malloc(strlen(s));
    strcpy(copy, s);
    p->str = copy;
    free(copy);
    
    您分配了原始字符串的副本并立即释放它

    char *w = (char *)malloc(strlen(t->str));
    
    这行代码重用以前释放的内存,这就是为什么您得到相同的内容-指针是相同的


    注意,这种情况发生在非常简单的场景中,并且特定于您使用的c库。

    您的代码表现出未定义的行为。在调用
    free
    后,您不允许访问
    copy
    ,这就是您要做的。另外
    malloc
    ing
    strlen
    字符不会为
    strcpy
    malloc(strlen)添加的空终止符留下额外的字符-->
    malloc(strlen+1)不要认为
    malloc()
    free()
    作用于指针变量——它们分配/释放与指针变量本身分离的内存块。。。指针变量只是用来保存地址,以便您知道在哪里可以找到它。在处理完放入
    malloc()
    结果的指针变量后,不会释放该块——在处理完
    malloc()
    ed的内存块后,会释放该块(尽管在此之前需要将其地址保留在某个位置)。如果不在create()函数中释放copy,将其释放为clean,是否也有效()像这样的方法:free(t->str);取决于你正在尝试做什么。当你不再需要字符串时,你需要释放它。如果你太早释放它,你会得到奇怪的行为,包括崩溃和损坏。如果你释放得太晚,你会有内存泄漏-欢迎来到CAh,好的,这是有意义的。同样对于p->str=strdup(s);在我的clean()中函数,我是否也需要释放(p->str);或者释放p,帮我解决这个问题吗?在c中,魔法不会发生任何事情,释放p不会释放p指向的任何东西,它不知道你没有另一个指针指向同一个字符串。但是在你的情况下,你应该释放(p->str);释放(p);因为我们知道p->str是一个“私有”副本
    #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;
    }
    
    char * copy = (char*)malloc(strlen(s));
    strcpy(copy, s);
    p->str = copy;
    free(copy);
    
    char *w = (char *)malloc(strlen(t->str));