为什么我可以在Python中访问看似随意的内存地址?

时间:2015-05-24 14:56:00

标签: python memory numpy cpython

在NumPy中使用strides我意识到你可以很容易地超越数组的界限:

>>> import numpy as np
>>> from numpy.lib.stride_tricks import as_strided
>>> a = np.array([1], dtype=np.int8)
>>> as_strided(a, shape=(2,), strides=(1,))
array([  1, -28], dtype=int8)

像这样我可以读取数组外的字节并写入它们。但我不明白这是怎么回事。为什么操作系统不能阻止我?在抛出Segmentation fault之前,我似乎可以离开这个数组至少100 KB。

我唯一能想到的是这个内存空间是由我的Python进程直接分配的。 NumPy会这样做吗?这个空间有固定的尺寸吗?还有什么其他对象?

2 个答案:

答案 0 :(得分:3)

这里有两种不同的内存分配器:

  1. 操作系统,可在Unix下访问,例如: brk(2)mmap(2)。这通常会为您提供您所要求的,但它不是非常用户友好。
  2. C运行时堆,可通过malloc(3)free(3)访问。这可能会或可能不会立即将释放的内存返回给操作系统。如果性能更高,它也可以将分配舍入到最近的页面。这通常以(1)。
  3. 的形式实现

    大多数应用程序,包括NumPy和Python,使用(2)而不是(1)(或者它们在(2)之上实现它们自己的内存分配器)。结果,根据(2)的无效存储器可能仍然根据(1)有效。如果违反方法(1)的规则,您只会遇到段错误。您也可能正在与堆上的其他活动对象进行交互,这很可能导致您的程序以任意方式行为异常,even if you are not changing anything

答案 1 :(得分:0)

Python和numpy是用C构建的,它没有内置的内存保护。内存分配在“堆”中,这是一个很大的内存块。由于所有对象都在那里分配,因此存储区域非常大并且充满了任何类型的对象。写入此内存可能会导致程序崩溃。