为什么我可以访问Python中看似任意的内存地址?
在NumPy中使用时,我意识到您可以轻松地越过阵列的边界:为什么我可以访问Python中看似任意的内存地址?,python,memory,numpy,cpython,Python,Memory,Numpy,Cpython,在NumPy中使用时,我意识到您可以轻松地越过阵列的边界: >>> 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)
>>> 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)
像这样,我可以读取数组外部的字节,也可以写入它们。但我不明白这怎么可能。为什么操作系统不能阻止我?在抛出分段错误之前,我似乎至少可以离开这个数组100 KB
我唯一能想到的是,这个内存空间是由我的Python进程直接分配的。NumPy会这么做吗?这个空间有固定的尺寸吗?还有什么其他对象?这里有两种不同的内存分配器:
操作系统,可在Unix下使用或访问。这通常会给你确切的要求,但它不是非常友好的用户
C运行时堆,可通过和free(3)
访问。这可能会也可能不会立即将释放的内存返回到操作系统。如果性能更好的话,它还可以将分配四舍五入到最近的页面。这通常按照(1)实现
大多数应用程序,包括NumPy和Python,使用(2)而不是(1)(或者它们在(2)之上实现自己的内存分配器)。结果,根据(2)无效的存储器根据(1)仍然有效。只有在违反方法(1)的规则时,才能获得segfault。也有可能您正在与堆上的其他活动对象交互,这极有可能导致您的程序以任意方式出现错误行为。Python和numpy是用C构建的,C没有内置内存保护。内存在“堆”中分配,堆是一大块内存。因为所有的对象都分配在那里,所以内存区域非常大,并且充满了任何类型的对象。写入此内存可能会使您的程序崩溃。您是否阅读过例如?是的,没有解释这一点。我认为说SEGFULT仅因违反方法(1)而导致是不正确的。根据我自己的调查(下面的答案),只有内存映射才能定义何时抛出segfault。还是我错了?警卫页面呢?我不太明白。尽管操作系统已经为读取访问准备了一个块,但在尝试读取时仍然可能引发错误吗?@jasaarim:malloc使用mmap和brk。Python使用malloc。“内存映射”是mmap,它本身就是(1)的一部分。但如果不是这样,我会感谢你的回答。这很有帮助,也让我更多地思考这个问题。哦,对不起,现在我明白了。是的,你可能是对的。