C++ 您可以从单独的程序中删除动态分配的内存吗?

C++ 您可以从单独的程序中删除动态分配的内存吗?,c++,memory-management,virtual-address-space,C++,Memory Management,Virtual Address Space,这个问题纯粹出于好奇。我最近了解到,如果在堆中动态分配内存空间,那么删除内存空间是非常重要的。我的问题是,是否有可能使用一个不同的C++程序删除动态分配的内存空间,如果内存空间的地址已知,则创建一个内存空间? 下面是一个例子: 代码01.CPP CODE01.CPP的输出 0x7c1640 代码02.CPP 这样行吗?如果我先运行code01.cpp,然后立即运行code02.cpp,堆中的内存会被删除吗?任何现代操作系统都会为这两个程序创建一个单独的虚拟地址空间。因此,您在code01.cpp

这个问题纯粹出于好奇。我最近了解到,如果在堆中动态分配内存空间,那么删除内存空间是非常重要的。我的问题是,是否有可能使用一个不同的C++程序删除动态分配的内存空间,如果内存空间的地址已知,则创建一个内存空间? 下面是一个例子:

代码01.CPP

CODE01.CPP的输出

0x7c1640

代码02.CPP


这样行吗?如果我先运行code01.cpp,然后立即运行code02.cpp,堆中的内存会被删除吗?

任何现代操作系统都会为这两个程序创建一个单独的虚拟地址空间。因此,您在code01.cpp中打印的地址仅与该程序相关,您无法从code02.cpp访问地址空间


因此,为了回答您眼前的问题:运行cpp02.cpp不会以任何方式影响仍在运行的cpp01.cpp的状态。

任何现代操作系统都会为这两个程序创建单独的虚拟地址空间。因此,您在code01.cpp中打印的地址仅与该程序相关,您无法从code02.cpp访问地址空间


因此,为了回答您眼前的问题:运行cpp02.cpp不会以任何方式影响仍在运行的cpp01.cpp的状态。

在大多数现代操作系统上,简短的答案是否定的。 大多数操作系统使用,这意味着程序A中的0x7c1640不一定是程序B中的0x7c1640。为了实现这一点,您必须为此编写一个没有内存保护的自定义操作系统,此时任何程序都可以覆盖任何其他程序,这是一个主要的安全漏洞

A提供了虚拟地址如何被占用的下图。每个程序都会得到操作系统转换的假内存地址,因此每个程序都会得到不同的堆,并且不能通过内存直接交互,至少在公共虚拟内存系统上是这样


在大多数现代操作系统上,简单的答案是否定的。 大多数操作系统使用,这意味着程序A中的0x7c1640不一定是程序B中的0x7c1640。为了实现这一点,您必须为此编写一个没有内存保护的自定义操作系统,此时任何程序都可以覆盖任何其他程序,这是一个主要的安全漏洞

A提供了虚拟地址如何被占用的下图。每个程序都会得到操作系统转换的假内存地址,因此每个程序都会得到不同的堆,并且不能通过内存直接交互,至少在公共虚拟内存系统上是这样


分配给操作系统的任务之一是确保一个过程不会伤害另一个过程。这意味着防止一个进程以任何方式直接影响另一个进程使用的内存

有几种机制可以实现这一点,但它们都无法实现这一想法

如果我知道这个进程中使用的指针的值,那么我可以通过这个进程对它的内存做些什么

因为这正是操作系统应该阻止的


也就是说,许多操作系统提供了用于进程间通信的特殊通道,您可以滥用这些通道来允许类似的操作。但是您必须进行操作,细节取决于操作系统。

分配给操作系统的任务之一是确保一个进程不会伤害另一个进程。这意味着防止一个进程以任何方式直接影响另一个进程使用的内存

有几种机制可以实现这一点,但它们都无法实现这一想法

如果我知道这个进程中使用的指针的值,那么我可以通过这个进程对它的内存做些什么

因为这正是操作系统应该阻止的


也就是说,许多操作系统提供了用于进程间通信的特殊通道,您可以滥用这些通道来允许类似的操作。但您必须进行操作,细节取决于操作系统。

要清楚,在CODE01中,当程序结束时,内存将被清除。如果对象具有析构函数,则可能无法正确清理。但在本例中,您处理的是int,所以这无关紧要。如果你担心内存,那么当程序结束时,分配的内存总是会被释放。那么你就错了。一旦程序终止,所有内存都将返回给OSA,现代操作系统将为每个进程提供单独的虚拟地址空间。地址在进程之间没有意义。@MarekR我不明白这为什么太宽泛了?只需回答一个问题,说明内存空间不是共享的。这是一个很好的问题。普通的现代桌面平台不支持此功能。有一些旧的平台在今天并不普遍使用,它们可以做到这一点,例如,使用操作系统分配内存块的旧Amiga,使用协作内存块管理的旧Mac。可能有现代嵌入式平台也可能
提供可执行覆盖和共享内存池的功能。要清除,在CODE01中,当程序结束时,内存将被清除。如果对象具有析构函数,则可能无法正确清理。但在本例中,您处理的是int,所以这无关紧要。如果你担心内存,那么当程序结束时,分配的内存总是会被释放。那么你就错了。一旦程序终止,所有内存都将返回给OSA,现代操作系统将为每个进程提供单独的虚拟地址空间。地址在进程之间没有意义。@MarekR我不明白这为什么太宽泛了?只需回答一个问题,说明内存空间不是共享的。这是一个很好的问题。普通的现代桌面平台不支持此功能。有一些旧的平台在今天并不普遍使用,它们可以做到这一点,例如,使用操作系统分配内存块的旧Amiga,使用协作内存块管理的旧Mac。有可能是现代嵌入式平台,也可以提供能力可执行的覆盖和共享内存池。即使你能够在OS内存保护中工作,这两个进程仍然会使用他们自己的C++堆,并拥有自己的控制结构。释放到错误的进程堆将是一场灾难。要使其工作,您必须使用该语言的新/删除机制实现自己的堆管理seaprate。假设两个进程内存映射一个公共文件,然后将内存用于对象存储。在这种情况下,指针是文件偏移量。正如我所说,你必须在它的工作,但在这方面,你可以让进程B负责释放进程A插入的对象。即使你能够在OS内存保护工作,这两个进程仍然会使用他们自己的C++堆与他们自己的控制结构。释放到错误的进程堆将是一场灾难。要使其工作,您必须使用该语言的新/删除机制实现自己的堆管理seaprate。假设两个进程内存映射一个公共文件,然后将内存用于对象存储。在这种情况下,指针是文件偏移量。正如我所说,您必须处理它,但在这种情况下,您可以让进程B负责释放由进程A插入的对象。
#include <iostream>
using namespace std;

int main() {
    int *a = new int;
    cout << a;
    int foo;
    cin >> foo;  // for blocking the program from closing.
    return 0;
}
#include <iostream>
using namespace std;

int main() {
    int *a = (int*)0x7c1640;
    delete a;
    return 0;
}