2017-09-01 135 views
0

我有点困惑与字符指针的概念,所以我做了一个简单的代码只是打印由用户(我)提供了我的名字。我也想练习malloc,所以我引用了指向RAM中某个内存的指针,但是我真的不知道在“sizeof(char)*”之后应该放什么,因为这是用户输入,尚未确定。 此外,这样做后,我释放的内存,但我得到了命令行上一个错误消息说:char指针和malloc的

*** Error in `./char': double free or corruption (fasttop): 0x00000000017fe030 *** 
Aborted 

好像我释放了相同内存的两倍或东西,但我不知道该怎么删除或添加。请帮忙!

#include <stdio.h> 
#include <cs50.h> 

int main (void) 
{ 

    char *strings = malloc(sizeof(char) * 10); 


    printf("What is your name?\n"); 

    //wait for use to type his/her name 
    strings = get_string(); 


    printf("Hello %s\n", strings); 

    free (strings); 

    return 0; 
} 
+3

什么是get_string?它是否定义了C语言?你应该通过分配的内存来获取字符串,并在那里填充数组。不覆盖。请添加代码'get_string' –

+0

根据https://cs50.stackexchange.com/questions/21617/whats-the-c-equivalent-for-string-input-getstring的答案,'cs50.h'具有函数名称是'GetString()'而不是'get_string()'。 – rsp

+1

运行时应该没有问题,只是内存泄漏。你是否复制并粘贴或重新输入? – molbdnilo

回答

6

线strings = get_string();实际上分配由get_string()返回到strings值。它不会将它写入您分配的内存中。

因此,由malloc()返回的值已被覆盖(并在此情况下丢失)。

free(strings)被释放任何get_string()返回。这个问题没有提供代码,但大概它是无效的free()它。

因为运行时间告诉你它被释放两次我猜你已经在get_string()中分配了内存,然后释放它并返回一个无效指针。

如果你要使用的内存分配,你需要更改get_string()接受指针:

void get_string(char *str){ 
    //Do whatever writing you value into str[] as an array of char.. 
} 

良好做法是有:

void get_string(char *str, size_t max){ 
    //Do whatever writing you value into str[] as an array of char.. 
    //Use max to avoid writing beyond the end of the space allocated... 
} 

然后调用为get_string(strings,10);

编辑:经过一番研究,已发现缺陷。 get_string()不直接free()返回,但它增加了其在退出释放由图书馆进行的分配列表(在一个名为teardown()atexit()或其他编译器相关的功能注册的函数)的字符串。

也就是说设计差,因为消费者提供代码,本身没有安全的方式释放其在典型使用情况下不会被要求为整个应用程序运行内存。 get_double()更糟糕的是,因为它永远不会返回分配的数据,但从来没有重用它,无异于直接内存泄漏。

的代码应该:

  1. 顺应文档,并要求消费者代码free()字符串(也许将其重命名为说get_string_alloc()为清楚起见)。
  2. 发售库程序来释放字符串(get_new_string()release_string()

没有转向用C分配内存的所有权,但持有到它的执行剩余非常好的方式绝对不是答案。 许多图书馆去圆的房屋推到分配代码的消费者,但是这是繁重时所需的空间的全尺寸不能被称为诸如这里。

我建议把_alloc()放在任何返回消费者代码必须稍后必须free()的对象的末尾。

所以提出的问题的答案是删除malloc()free(),因为库处理两者。但是,如果你的程序,使该功能很多电话和其他人的内部依赖它(如get_double()),你可能耗尽内存,因为该库是坐在死角提防。

+1

“推测它是无效的释放()它。” - [不幸的是,它*是*有效的](https://reference.cs50.net/cs50/get_string)。我继续怀着我最大的愿望,扼杀设计'cs50.h'库的恶魔,原因有很多,包括但不限于'typedef char * string;'那里的权利应该告诉你这个头是多么不光彩。 – WhozCraig

+0

@WhozCraig然后我认为在cs50代码中可能有问题。你不应该在做'malloc()',因为docco说它分配空间。但仅仅因为你的代码泄露了10个字节,不应该导致消息说你已经释放了一些东西。它可能只是在执行结束时发出一个错误,一个10字节的块没有被释放。 你从哪里得到代码?你能发布'get_string()'的源吗? – Persixty

+3

显然,根据您使用的cs50版本,[库可能会从'get_string']管理自己的堆分配链(https://github.com/cs50/libcs​​50/blob/develop/docs/get_string.adoc ),并在进程退出时释放它们(毫无意义,因为操作系统将回收所有内存而不考虑)。在这样做的时候,如果在用户代码中也做了双免费的话。不同版本的库不这样做。因此,遵循旧教程的人会编写代码,使用更新的lib会产生一个双免费的代码。这可能是这里发生的事情。 – WhozCraig

0

你不包括get_string()代码,但你覆盖strings与它的返回值是错误的。您传递给free()地址必须来自malloc(),似乎你违反该(除了失去原来的返回地址为您10个字节)。

假设get_string()返回静态存储器(即您不需要释放它),您可以在不涉及malloc()的情况下执行此操作。

如果你真的想,这样的事情可能工作:

printf("What is your name?\n"); 
const char *name = get_string(); 
const size_t nlen = strlen(name); 
char * const name_copy = malloc(nlen + 1); 
if(name_copy != NULL) 
{ 
    memcpy(name_copy, name, nlen + 1); 
    printf("Hello %s (from my own memory!)\n", name_copy); 
    free(name_copy); 
} 

这是颇为曲折,但你的想法。

+0

这个假设是错误的:'get_string'返回调用者必须释放的内存。您可以简单地使用'strdup'作为复制部分。 ;) – Gerhardh

2

的问题是你的get_strings覆盖您最初malloc。指针值是一个值。通过与别的东西等同,你更换malloc值。

0

首先,你必须创建将由*串指出动态存储器。但是然后你使用*字符串指针指向本地字符串(来自get_string()函数)。当你调用free时,程序试图删除本地(堆栈)引用并抛出错误。

为了解决这个错误,程序应该是

#include <stdio.h> 
#include <cs50.h> 

int main (void) 
{ 

char *strings = malloc(sizeof(char) * 10); 


printf("What is your name?\n"); 

//wait for use to type his/her name 
strcpy(strings, get_string());  // Use strcpy instead of assigning 


printf("Hello %s\n", strings); 

free (strings); 

return 0; 
} 
0

内存在所述语句的字符串= get_string分配(); 。你不要有它的malloc(字符*字符串=的malloc(的sizeof(字符)* 10); )。没有的malloc它会正常工作

0

char *strings;

  • 无需新的malloc返回的字符串从get_string()函数已经在堆上,你只需要拿起指向第一个字符的指针。(get_string() function reference

strings = get_string();

printf(“Hello%s \ n”,strings);

  • 打印字符串后,你应该释放分配给它的内存,因为它是在get_string()函数的引用说明上堆(通过malloc的)

存储串;内存必须由调用者释放到 避免泄漏。

我觉得一切是好的,试试这个代码:

#include <stdio.h> 
#include <cs50.h> 

    int main (void) 
    { 
     char *strings; 

     printf("What is your name?\n"); 

     //wait for use to type his/her name 
     strings = get_string(); 

     printf("Hello %s\n", strings); 

     free (strings); 

     return 0; 
    } 
+0

我同意不需要'malloc'并导致内存泄漏。但是,这怎么会导致错误消息“双倍免费”? – Gerhardh

+0

@Gerhardh问题是,编译器获取在麻烦,因为他会覆盖指针的char *字符串= malloc的(的sizeof(char)的* 10);从这个malloc获得get_string()返回指针值,所以他自动丢失了一个指针,用来释放他最初配对的指针,现在它仍然没有被释放。 – Lazar

+0

我知道,但是内存泄漏是基本上什么是“双自由或已损坏”错误通常表示相反。该错误消息指示某些内存已释放两次或内存边界被覆盖。该错误消息与该内存泄漏不匹配。必须有别的东西。这是相当奇怪给出的一小段代码... – Gerhardh