【问题标题】:mallocing string in C在 C 中分配字符串
【发布时间】:2017-01-23 10:32:07
【问题描述】:

我不太清楚malloc 是如何工作的。

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

int main() {

 char * string = (char*) malloc(sizeof(char));
 string = "abc";

 int * test = (int*) malloc(1 * sizeof(int));
 *(test) = 5;
 *(test + 1) = 6;


}

我预计这会输出一个错误,因为我指定给字符串的值大于一个字符,但它似乎编译得很好。

我有几个问题:

  1. 现在“字符串”会保存在哪里?它是在我分配的一个空间之后堆上的内存空间上吗?

  2. 为什么char让我直接指定而int只能通过指针指定?

我真的不知道我在这里做什么

【问题讨论】:

  • @PaulMcKenzie 我正在学习麻省理工学院的 ocw 课程,ppt 示例使用了这个,但你的权利这似乎很愚蠢,感谢提供额外的信息
  • *(test + 1) = 6; 写入越界
  • 您所写的是未定义的行为。老实说,如果您不知道如何正确地将字符串分配给字符指针,那么您真的还没有准备好malloc
  • @DavidHoelzer 说实话,没有人准备好接受malloc

标签: c char malloc heap-memory


【解决方案1】:

这段代码

string = "abc";

将字符串常量"abc"的地址分配给string变量,即char *。从您的 malloc() 调用返回的内存地址(位于 string 中)被覆盖并丢失。

【讨论】:

    【解决方案2】:

    除了其他答案:

    你可能想要这个:

    char *string = (char*) malloc(sizeof(char) * 100);  // allocate space for 100 chars
    strcpy(string, "abc");  // copy the "abc" into the memoory location pointer by string
    

    而不是这个:

    char *string = (char*) malloc(sizeof(char));   // << this allocates only a single char
    string = "abc";
    

    *(test) = 5;
    *(test + 1) = 6;
    

    最好写成:

    test[0] = 5;
    test[1] = 6;
    

    这是严格等价的,只是可读性问题。

    分配的内存太少:

    如果您只为 1 个字符分配内存,如下所示:

    char *string = (char*) malloc(sizeof(char));  // allocate space 1 char
    strcpy(string, "abc");  // copy the "abc" into the memoory location pointer by string
    

    那么您的程序仍然可以正常编译,但在运行时字符串将被部分复制到未分配的内存中,这会导致未定义的行为(谷歌“未定义的行为”)。

    【讨论】:

    • 但我只为一个字符分配空间,那么当我为另一个变量分配空间时,持有“bc\0”的地址会被覆盖吗?编辑:是的,您在我的评论完成之前回答了谢谢
    • 幻数是非常糟糕的做法。让新程序员养成坏习惯是个坏主意。
    • @DavidHoelzer 你是对的,但我不想让事情变得过于复杂,无论如何,OP 的程序只是一个测试程序。
    【解决方案3】:

    'string' 现在会保存在哪里?

    char * string = (char*) malloc(sizeof(char));
    string = "abc";
    

    string 现在指向“abc”(文字字符串) - 初始动态分配(在堆中)已丢失轨道,您有内存泄漏。

    【讨论】:

      【解决方案4】:

      我会给你一个真实的例子。

      假设 A 先生住在地址“abc”。现在,一些B先生开始住在某个地址“xyz”。很快,B先生的地址“xyz”被重命名为“abc”。现在,如果你去地址“abc”,你会遇到B先生,而不是A先生。但是,这并不意味着A先生的地方被拆除了。简单来说就是A先生的居住区现在没有可达地址,丢失了。

      同样,你malloc'ed 到string 然后将string 重新分配给“abc”的内存,意味着string 之前有一个指向malloc'ed 内存的地址。稍后,您的“abc”被写入某个内存,该内存的地址存储在string 中。因此,永远丢失了malloc'ed 内存,这称为内存泄漏。

      【讨论】:

        【解决方案5】:

        编译器不会阻止您执行允许的操作 - 但是您可能会收到 1) 的警告,因为 string 已分配并且在重新分配之前未使用(前提是请求编译器输出相关警告)。

        至于 2),您调用了一个恰好是 malloc 的函数,其参数恰好对于您想要使用 malloc 返回的指针执行的用法来说太小了,但是由于语法是正确,编译器不会抱怨。

        回答

        1) string 指向 "abc" 并且之前来自 malloc 的值丢失了

        2) 你也可以使用test[0] = 5;

        2) 的行为是未定义的行为(越界访问数组)。

        【讨论】:

          【解决方案6】:

          一开始动态分配了一个字符大小的内存。

          char * string = (char*) malloc(sizeof(char));
          

          然后用字符串“abc”的第一个字符的地址重新分配指针。

          string = "abc";
          

          结果动态分配的内存地址丢失,程序出现内存泄漏。

          如果程序是用 C++ 编写的,那么这个语句

          string = "abc";
          

          可能会出现编译器诊断消息,因为 C++ 中的字符串文字具有常量字符数组类型,并且指针 string 应该声明为

          const char *string;
          

          对于字符串文字,它们具有静态存储持续时间,并且在 main 获得控制权之前分配。通常所有的字符串字面量都在所谓的字符串字面量池中。

          代替这种说法

          string = "abc";
          

          你可以写

          strcpy( string, "abc" );
          

          在这种情况下,程序具有未定义的行为。但是,由于函数malloc 通常分配的最小内存范围等于等于 16 字节的段落的值,因此它可以继续成功工作。

          【讨论】:

          • 这是一道 C 题。 C++ 代码的行为无关紧要
          • @M.M 没有任何“不相关”的信息。在 C 1) 中,指针也可以用限定符声明 const 在 C 中可以使用与 C++ 中相同的方法; 2) C 和 C++ 中相同结构的任何比较都非常有用,有助于更好地理解 C 和 C++。
          猜你喜欢
          • 2015-09-15
          • 1970-01-01
          • 2020-07-23
          • 2011-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多