我们可以访问悬空指针/访问类似于反病毒的其他进程内存吗?这种进程间访问是否​​可能发生内存泄漏?

时间:2014-03-19 18:09:46

标签: c++ pointers operating-system coredump antivirus

我总是认为尝试访问动态释放(首先分配的和以后删除/释放的)内存最终会导致coredump。 但是当我执行下面的代码时,它成功完成了。

 int* ptr = new int(3);
delete ptr;

cout << "value : " << *ptr << "  " << ptr;

所以我继续创建了一个悬空指针并明确地尝试访问内存,但现在它被抛弃了。

int* aptr;
aptr = (int*)0x561778;
cout << "value : " << *aptr << "  " << aptr;

1)如果我们无法访问超出给定进程空间的内存,那么在我释放/释放内存后,我是如何访问内存的呢? (第一个例子)

此外,如果是这种情况,那么反病毒如何扫描其他进程分配的内存?

2)如果我动态分配但不释放内存,则会导致内存泄漏。 但如果我的整个过程被杀死怎么办?或完成执行,所以关闭。 那么OS不会确保清理分配给这个过程的所有资源吗?那么内存泄漏只会发生在长期的进程中吗?

如果这是真的,那么当我明确地尝试访问另一个进程的内容时,操作系统如何确保它不会释放这个内存?

1 个答案:

答案 0 :(得分:4)

  

1)如果我们无法访问超出给定进程空间的内存,那么如何   是我在释放/释放后能够访问内存吗?   (第一个例子)

因为C或C ++运行时保持&#34;堆&#34;内存,当你调用free或delete时,内存实际上不会被渲染为进程无法使用,它只是被放回到&#34; free memory&#34;堆的区域,因此它将被重用。这样做是因为它对于一个进程分配一些内存,释放它,再分配一些,释放它等等非常普遍。例如

void readfile(const std::string& fname)
{
    std::ifstream f(fname.c_str());
    std::string* content = new std::string;
    while(cin.getline(content))
    {
       ...
    }
    delete content;
}

这个函数(愚蠢的,因为我们不应该分配std::string)将首先为std::string分配空间,然后在std:string内为内容[可能在几个部分]分配空间getline调用正在读取文件。可能还有其他内存分配,例如`std::ifstream

堆的设计目的是最大限度地减少它要求操作系统将内存从全局物理内存映射/取消映射到特定进程的次数,因为它非常昂贵&#34;在几乎所有处理器中映射和取消映射虚拟内存的性能方面(特别是,从其他内核卸载现已解散的内存页面将涉及向另一个处理器发送消息,另一个处理器停止其正在执行的操作,更新它的虚拟映射,然后回答&#34;我已经完成了这个&#34;,然后继续它的位置)。当然,如果操作系统在进程停止使用时没有取消映射进程的内存,那么相同的进程确实可以使用&#34;该内存地址用于查找其他进程的内容 - 这将是一件坏事,因此操作系统将强制所有处理器内核放弃它的内存映射,然后该内存位可以再次用于另一个进程[至少]。

编辑:为了澄清,堆有时会将内存释放回操作系统。例如,如果你进行大量分配,然后释放相同的分配,它可能会立即取消映射,因此在释放后你将无法访问内存。在释放内存之后对内存的任何访问都是未定义的行为,运行时可以(并且经常会)在那时对内存做任何喜欢的事情。最常见的情况是:

  1. 保持原样,但把它放在&#34;释放&#34;桩。
  2. 将它保存在释放的记忆中,但要填充一些&#34;魔法&#34;用于检测何时被写入的模式,因此&#34;免费使用&#34;可以被检测到(非常好的东西可以检测!)
  3. 内存未映射,不再可用于当前进程。
  4. 内存几乎立即被分配用于其他目的,并再次使用。
  5. 相同的操作系统可以在不同的时间以几乎任何顺序使用这些方案中的任何一种。

      

    此外,如果是这种情况,那么反病毒如何扫描内存   由其他进程分配?

    完全不同的问题。他们使用调试接口来读取另一个进程的内存,或者他们自己的内核驱动程序功能使用内核函数,允许任何进程读取任何其他进程的内存 - 毕竟,内核可以做任何事情。 [实际上,反病毒软件通常对从文件加载到内存中的内容更感兴趣,因此应用文件访问过滤器来检查文件的读/写数据,而不是扫描内存中的内容]

      

    2)如果我动态分配但不释放内存,那么它会   导致内存泄漏。但如果我的整个过程被杀死怎么办?要么   完成执行,所以关闭了。然后OS不会确保清洁   分配给这个过程的所有资源?内存泄漏也会如此   仅适用于长期流程?

    一个过程&#39;进程终止时释放内存。总是,每一次。或者你可以通过启动一个分配相当数量的内存,故意杀死它,再次运行它,杀死它,运行,杀死等的进程来使系统失败。那会是一件坏事,对吗?

    你当然可以快速泄漏内存。尝试:

     std:string str;
    
     str.append(100000, 'x');
     std::vector<std::string> v;
    
     int i = 0;
     while(1)
     {
         std::cout << "i=" << i << std::endl;
         v.push_back(str);
    

    在系统开始转换之前不会花费很多秒钟,不久之后它会被杀死(如果你不感到厌倦并先杀死它)。如果你这样做,预计linux系统会得到相当的反应......

      

    如果这是真的,那么当我明确地尝试访问的内容时   另一个过程如何操作系统确保它不会释放它   存储器?

    正常进程将无法访问属于另一个进程的内存 - 只能通过有限的接口(如调试接口或专门编写的内核驱动程序)来执行此操作。或者通过使用OS支持的共享内存,当然,在操作系统的许可下,相同的内存映射到两个不同的进程。

    这些访问另一个进程的内存的方法将涉及某种形式的&#34;引用计数&#34; [实际上同样适用于例如,如果进程当前正在系统调用中试图保存1000MB文件,并且该进程是由于某种原因而被杀死 - 说另一个线程导致不可恢复的错误] - 操作系统会跟踪许多&#34;用户&#34;有一段特定的记忆,所以它不会从某个过程(或其本身)的脚下拉出地毯。

相关问题