字符指针和 malloc

Char Pointers and malloc

我对字符指针的概念有点困惑,所以我编写了一个简单的代码,只打印用户(我)提供的我的名字。我也想练习malloc所以引用了RAM中某块内存的指针,但是我实在不知道在"sizeof(char) *"后面放什么,因为那是用户输入,还没有定下来。 此外,这样做之后,我释放了内存,但我在命令行上收到一条错误消息:

*** 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;
}

您没有包含 get_string() 的代码,但您用 return 的值覆盖了 strings,这是错误的。您传递给 free() 的地址必须来自 malloc(),而且您似乎违反了这一点(除了丢失原始 returned 地址的 10 个字节)。

假设 get_string() returns 静态存储(即您不需要释放它)您可以在不涉及 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);
}

这很复杂,但你明白了。

问题是您的 get_strings 覆盖了您的初始 malloc。指针值是一个值。通过将它等同于其他东西,您 替换了 您的 malloc 值。

首先你已经创建了一个动态内存,它将被*strings指向。但是随后您使用 *strings 指针指向本地字符串(来自 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;
}

strings = get_string();行实际上将get_string()返回的值赋给了strings。它不会将其写入您分配的内存中。

因此 malloc() 返回的值已被覆盖(在本例中丢失)。

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

因为 运行-time 告诉你它被释放了两次我猜你已经在 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() 字符串 returns 而是将其添加到库进行的分配列表中,这些分配在退出时被释放(在一个名为 teardown() 的函数中 registered具有 atexit() 或其他依赖于编译器的功能)。

这是糟糕的设计,因为没有提供消费者代码自身释放内存的安全方法,而在典型的用例中,整个应用程序执行不需要内存。 get_double() 更糟,因为它从不 returns 分配的数据,但从不重用它,相当于直接内存泄漏。

代码应该是:

  1. 遵守文档并要求消费者代码 free() 字符串(为清楚起见,可以将其重命名为 get_string_alloc())。
  2. 提供一个库例程来释放字符串(get_new_string()release_string()

在 C 中没有很好的方法来转移已分配内存的所有权,但在剩余的执行过程中一直保留它绝对不是答案。 许多图书馆四处走动,将分配推到消费者代码上,但是当无法知道所需的 space 的完整大小时,这是很繁重的,例如这里。

我建议将 _alloc() 放在 returns 消费者代码稍后必须 free().

对象的任何函数的末尾

所以所提问题的答案是删除 malloc()free(),因为库同时处理这两个问题。但是请注意,如果您的程序多次调用该函数和其他内部依赖它的函数(如 get_double()),您可能 运行 内存不足,因为库已死 space。

在语句处分配内存:
strings = get_string();

您不必 malloc 它( char *strings = malloc(sizeof(char) * 10); )

没有 malloc 它会正常工作

char *strings;

  • 不需要新的 malloc,因为从 get_string() 函数返回的字符串已经在堆上,您只需要获取指向第一个字符的指针。 (get_string() function reference)

字符串=get_string();

printf("Hello %s\n", 字符串);

  • 打印字符串后,您应该释放为其分配的内存,如 get_string() 函数参考中所述

Stores string on heap (via malloc); memory must be freed by caller to avoid leak.

我认为其他一切都很好,试试这个代码:

#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;
    }