【问题标题】:How pointers allocate memory指针如何分配内存
【发布时间】:2015-08-24 20:58:05
【问题描述】:
#include<stdio.h>
int main()
{

  char *str;

  gets(str);

  puts(str);

return 0;
}

输出=分段错误

为什么会出现分段错误?

【问题讨论】:

  • 指针不分配内存。
  • 如果要分配内存,需要调用malloc()
  • str 只是一个指针。 str 指向哪个内存区域?不知道?我也没有,因为你还没有初始化它。它可能指向任何地方。你真的很幸运它崩溃了。
  • 建议:阅读更多关于指针的信息

标签: c pointers segmentation-fault gets


【解决方案1】:

“指针如何分配内存”这个问题的答案非常简单:它们不会。这就是您遇到分段错误的原因:从未初始化的指针访问数据是未定义的行为。

程序员必须分配内存,并将其分配给指针。例如,您可以使用malloc:

char *str = malloc(10);
fgets(str, 10, stdin);
puts(str);

关于上述修复需要注意的重要一点是使用fgets 而不是弃用的gets。这是因为fgets 让您告诉函数它可以在缓冲区中使用多少内存,而gets 假设它拥有所需的所有内存,从而导致缓冲区溢出。

【讨论】:

  • @ShubhamTiwari 欢迎您。如果这回答了您的问题,请考虑通过单击旁边的灰色复选标记来接受答案。这将使其他网站访问者知道您的问题已解决,并在 Stack Overflow 上为您赢得徽章。
【解决方案2】:

万一

 gets(str);

str 未初始化使用。作为一个自动局部变量,除非显式初始化,否则str 的内容是不确定的。它可能指向未分配给您的程序的内存位置。

使用(尝试写入甚至读取)未启动的内存会导致undefined behavior。分段错误是副作用之一。

也就是说,gets() 是纯粹的邪恶,因为可能存在缓冲区溢出问题。请改用fgets()。

【讨论】:

    【解决方案3】:

    当你声明一个指针时,你所做的只是留出空间来存储另一个对象的地址;您没有为其他对象本身留出任何空间。

    这是一个假设的内存映射(地址是凭空提取的,并不代表任何真实字架构,假设是 32 位字):

    Item        Address        0x00  0x01  0x02  0x03
    ----        -------        ----  ----  ----  ----
    str         0xfff86400       ??    ??    ??    ??  // ?? represents unknown byte value
    

    变量str 位于地址0xfff86400。由于您用auto 声明了str 存储持续时间(即在函数内)并且没有显式初始化它,所以它的值是indeterminate;它包含一个未知的位模式(很可能)不对应于您程序中的可写地址。 gets 尝试将数据写入此 invalid 地址,因此 段错误1。没有一个输入例程(fgets、scanf、fscanf、fread 等)会留出内存来存储实际输入;那是你的责任。

    当你想通过一个指针来操作某些东西时,你需要分配指针所指向的东西到。例如,您可以这样做:

    char buf[8] = "blah!";
    char *str = buf;
    

    这会留出一个缓冲区来存储最多 8 个字符,然后将该缓冲区的第一个元素的地址分配给 str,给我们这样的结果:

    Item        Address        0x00  0x01  0x02  0x03
    ----        -------        ----  ----  ----  ----
    buffer      0xfff86400      'b'   'l'   'a'   'h'
                0xfff86404      '!'    00    ??    ??
    str         0xfff86408       ff    f8    64    00 
    

    同样,您可以使用malloc 来动态地为str 分配内存以指向:

    char *str = malloc( BUF_SIZE );
    

    malloc 留出BUF_SIZE 字节来存储您的输入字符串,并将指向该空间的指针分配给str。


    1。严格来说,取消引用无效指针的行为是undefined;段错误是许多可能的结果之一。它可以很容易地破坏一些重要的东西,以便您的程序继续运行但现在具有管理员权限。

    【讨论】:

      【解决方案4】:

      你需要先分配你的str。 像这样:

      #include <stdio.h>
      
      int main()
      {
      
        char *str;
      
        str = malloc(4096);
        gets(str);
      
        puts(str);
      
        free(str);
        return (0);
      }
      

      这将允许在 str 中写入。

      为了更好地分配内存,最好知道您需要多少内存,而不是任意的“4096”。

      此外,当您不再需要它时,不要忘记使用 free()。

      【讨论】:

        猜你喜欢
        • 2021-06-22
        • 2015-04-21
        • 1970-01-01
        • 2016-02-21
        • 1970-01-01
        • 1970-01-01
        • 2022-09-24
        • 2013-05-31
        • 2021-11-29
        相关资源
        最近更新 更多