C - 在内存被释放()后访问数据?

2023-11-27

我读了很多关于标准 C 中的 malloc() 和 free() 的内容。据我了解,您malloc()只为了一次记忆,然后你free()同样的记忆只有一次。这可能是不好的做法,但我明白,在你之后malloc()内存,您可以定义多个指向它的指针。而一旦你free()那些指针中的任何一个,分配的内存被取消分配吗?

考虑这个玩具示例:

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

int main(){

    char* p = (char*)malloc(10 * sizeof(char));     // allocate memory
    int* q = (int*)p;                               // pointer to the same block of memory
    *p = 'A';                                       // Input some data
    printf("TEST::  %c %d\n", *p, *q);              // Everything's ok so far...
    free(p);                                        // free() my allocated memory?
    sleep(10);                                      // wait
    printf("%c\n", *q);                             // q now points to de-allocated memory
                                                    // shouldn't this segfault?

    free(q);                                        // *** SEGFAULTS HERE ***

    return 0;
}

输出是:

[Linux]$ ./a.out
TEST::  A 65

*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001ac4010 ***
======= Backtrace: =========
...lots of backtrack info...

所以我假设当我free()第一个指针,考虑内存free()编辑,但是数据值我在这块内存中写的仍然“在那里”,这就是为什么我可以通过第二个指针访问它们?

(我并不是说这是一个好主意,我只是想理解系统的逻辑。)


当您分配内存时,您将获得一个指向某个空间的指针,当您释放它时,您将其返回给系统。通常,您仍然可以访问该内存,但在释放内存后使用它是非常糟糕的。

确切的行为是未定义的,但在大多数系统上,您可以继续访问内存,或者出现段错误。

您可以尝试的一个有趣的实验是在释放该指针后尝试分配更多内存。在我尝试过的大多数系统上,您都会得到相同的块(如果您依赖于已释放块中的数据,这是一个问题)。您的程序最终将使用两个指针,但由于它们指向相同的物理数据,因此您将覆盖您自己的数据!

这样做的原因是,当您 malloc 数据时(当然取决于 malloc 实现),malloc 首先从操作系统请求一个数据块(通常比 malloc 请求大得多),然后 malloc 会给您该数据的一部分记忆。不过,您将能够访问最初从操作系统获得的内存 malloc 的任何部分,因为对于操作系统来说,它是您的程序内部使用的所有内存。当您进行释放时,您是在告诉 malloc 系统该内存是空闲的,并且可以稍后返还给程序。

在 malloc 区域之外写入是非常危险的,因为

  1. 它可能会出现段错误,具体取决于您的 c 实现
  2. 您可以覆盖 malloc 所依赖的元数据结构,这会在稍后释放/malloc 更多数据时导致非常糟糕的问题

如果您有兴趣了解更多信息,我建议您通过 valgrind(泄漏检测器)运行您的程序,以更好地了解已释放/未释放的内容。

PS:在没有操作系统的系统上,您很可能根本不会出现段错误,并且您可以随心所欲地在任何地方进行写入。操作系统负责触发段错误(当您写入/读取您无权访问的内存时,例如内核或受保护的内存)

如果您有兴趣了解更多信息,您应该尝试编写自己的 malloc,和/或阅读/了解内存管理操作系统的知识。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C - 在内存被释放()后访问数据? 的相关文章

随机推荐

  • 如何指定属性必须是(比如说)整数列表,而不仅仅是列表?

    使用属性库和 Python 3 6 我认为以下内容可以让我指定x and y只能包含整数 import attr attr s class C x List int attr ib not working y attr ib type Li
  • 内存目标 BTS 为何会比 load / BTS reg,reg / store 慢得多?

    在一般情况下 可以使用内存或寄存器操作数的指令如何会比内存操作数慢 mov mov gt 指令 gt mov mov 基于发现的吞吐量和延迟Agner Fog 的说明书 以我为例 查看 Skylake p238 我看到以下数字btr bts
  • Resharper 格式化链式方法

    R 中是否有设置将链接方法格式化为从实例化类的相同字符开始 我想要的是 var foo new FooDataBuilder WithDate myDate WithBar myBar Build R 给了我什么 var foo new F
  • 如何在 Windows 中注册自定义 URL 协议?

    如何向 Windows 注册自定义协议 以便在单击电子邮件或网页中的链接时打开我的应用程序并将 URL 中的参数传递给它 Go to Start然后在Find type regedit gt 它应该打开注册表编辑器 Click Right
  • ASP.NET MVC 获取视图的最后修改日期/文件信息

    我需要在工作申请的每一页上注明最后修改日期 我曾经通过在 WebForms 母版页底部包含对 的引用来实现此目的 该引用将返回当前 aspx 页面的上次修改日期 我的代码甚至会检查关联的 aspx cs 文件 比较上次修改日期 并返回最近的
  • .Net枚举winforms字体样式?

    我一直在寻找一种使用 Net 框架列出给定字体的有效字体样式的方法 即使我必须 pinvoke gdi32 或其他一些 API 因为并非所有字体都属于 System Drawing FontStyle 枚举值 粗体 斜体 常规 删除线 下划
  • 自定义WPF窗口样式

    我正在尝试制作自定义窗口样式 目标是创建一个可以被我的应用程序中的每个窗口使用的模板 模板包含工具栏 标题和 窗口将使用的区域 问题是 当我使用我的样式时 我无法再添加网格和控件 App xaml
  • 在 __init__ 上使用 scrapy 管道中的参数

    我有一个 scrapy pipelines py 我想获得给定的参数 在我的 Spider py 中 它工作得非常完美 class MySpider CrawlSpider def init self host domain id args
  • 从非托管代码调用托管 .NET 代码的最佳方法

    我试图找到从非托管 C 代码调用托管 NET 代码的最佳执行方法 我在我的 C 应用程序中找到了有关托管 NET 的信息 并且我能够创建 pRuntimeHost 并毫无问题地启动它 ExecuteInDefaultAppDomain 似乎
  • 如何让 iOS 上的 tesseract 运行得更快?

    我在 ios 上的 tesseract ocr 上遇到了困难 一切工作正常 但速度真的很慢 单行数字的识别时间为 2 3 秒 我正在阅读视频流 我正在使用 tesseract 3 01 以及针对我的字体的自定义训练文件 这是我所做的 设置
  • Rails 3 中控制器特定的样式表:继承

    首先 我是 Rails 的新手 我正在 Rails 网站上工作 它有三个控制器 即application controller static pages controllers 和 users controller 它们在 app asse
  • 在 Hibernate 验证期间执行 EntityManager 查询的正确方法

    我是一个 Java EE EJB 菜鸟 但从我收集的文档和其他帖子来看 您无法在实体验证期间使用相同的实体管理器 会话查询数据库 一般来说 可移植应用程序的生命周期方法不应调用 EntityManager 或查询操作 访问其他实体实例或修改
  • Haskell 和惰性 Monads 评估

    在使用 monad 时 我经常遇到评估问题 现在 我了解了延迟求值的基本概念 但我不明白如何在 Haskell 中延迟求值 monad 考虑下面的代码 module Main where import Control Monad impor
  • Django 删除文件字段

    我正在 Django 中构建一个网络应用程序 我有一个上传文件的模型 但无法删除该文件 这是我的代码 class Song models Model name models CharField blank True max length 1
  • Tomcat 引起:java.util.zip.ZipException:打开 zip 文件时出错

    我有一个 spring mvc 项目 但它抛出了Caused by java util zip ZipException error in opening zip file当我通过 Tomcat 运行它时 如何确定哪个 jar 文件没有正确
  • 如何在IIS7.5中启用ASP经典

    我在 Windows 7 中运行 IIS 7 5 并且已经进入 打开或关闭 Windows 功能 并在 Internet 信息服务 万维网服务 应用程序开发功能 中启用了 ASP 完成此操作后 我开始收到 HTTP 404 错误 由于扩展名
  • 替换日期时间日期中的年份

    我有一个带有一列的表 dateDT 格式为日期时间和年份的变量输入 selYear 在我的 Select 中 格式为 int 如何使用变量输入替换表中日期中的年份并以日期时间格式返回结果 在选择中 我已尝试以下操作 但这返回错误的日期 年份
  • 使用下划线 groupby 按颜色对一组汽车进行分组

    我有一系列的汽车 car make nissan model sunny colour red 我将如何使用 underscore js 按颜色对数组进行分组 我尝试了一些组合 但我不太确定如何指定我的迭代器条件 var carsGroup
  • OSError:无法打开共享对象文件:即使文件位于文件夹中,也没有此类文件或目录

    我已经为此奋斗了很长一段时间了 我正在尝试安装 Yaafe 来提取音频特征 我按照这里的说明操作 https github com Yaafe Yaafe 一切都安装得很好 但是当我尝试运行测试文件 frames py 时 出现以下错误 F
  • C - 在内存被释放()后访问数据?

    我读了很多关于标准 C 中的 malloc 和 free 的内容 据我了解 您malloc 只为了一次记忆 然后你free 同样的记忆只有一次 这可能是不好的做法 但我明白 在你之后malloc 内存 您可以定义多个指向它的指针 而一旦你f