Python是内存安全的吗?

问题描述 投票:2回答:1

Deno是Node.js的新对手等等,Rust的内存安全特性在很多新闻文章中都有提到,有一篇特别的文章说Rust和Go的内存安全特性很好,Swift和Kotlin也是如此,但是后两者并没有那么广泛的用于系统编程。

Safe Rust才是真正的Rust编程语言。如果你所做的只是编写Safe Rust,你将永远不用担心类型安全和内存安全的问题。你永远不会忍受一个悬空指针,一个使用后的免费,或任何其他类型的未定义行为。

这引起了我的兴趣,想了解Python是否可以被认为是内存安全的,如果是或不是,安全或不安全的程度如何?

从一开始 记忆安全条 维基百科上甚至没有提到Python,而关于Python的文章似乎只提到了内存管理。这个是丹尼尔:

维基百科上的文章将类型安全与内存安全联系在一起,意思是说,不能像整数和字符串那样访问同一个内存区域。在这种情况下,Python 是类型安全的,你不能隐式地改变一个对象的类型。你不能隐式地改变一个对象的类型。

但即使这样似乎也只是暗示了两个方面的联系(使用了维基百科上的一个关联,这又是值得商榷的),对于Python是否可以被认为是内存安全的,并没有明确的答案。

python python-3.x memory-management memory-safety
1个回答
3
投票

维基百科 列表 以下是内存安全问题的例子。

Access errors: invalid read/write of a pointer
    Buffer overflow - out-of-bound writes can corrupt the content of adjacent objects, or internal data (like bookkeeping information for the heap) or return addresses.
    Buffer over-read - out-of-bound reads can reveal sensitive data or help attackers bypass address space layout randomization.

Python 至少尝试 来防止这些情况的发生。

    Race condition - concurrent reads/writes to shared memory

这在使用可变数据结构的语言中其实并不难做到。(函数式编程和不可变数据结构的拥护者经常使用这个事实作为他们的有利论据)。

    Invalid page fault - accessing a pointer outside the virtual memory space. A null pointer dereference will often cause an exception or program termination in most environments, but can cause corruption in operating system kernels or systems without memory protection, or when use of the null pointer involves a large or negative offset.
    Use after free - dereferencing a dangling pointer storing the address of an object that has been deleted.
Uninitialized variables - a variable that has not been assigned a value is used. It may contain an undesired or, in some languages, a corrupt value.
    Null pointer dereference - dereferencing an invalid pointer or a pointer to memory that has not been allocated
    Wild pointers arise when a pointer is used prior to initialization to some known state. They show the same erratic behaviour as dangling pointers, though they are less likely to stay undetected.

没有真正的方法来防止有人试图访问一个空指针。在C#和Java中,这导致了一个 例外. 在C++中,这 导致未定义的行为.

Memory leak - when memory usage is not tracked or is tracked incorrectly
    Stack exhaustion - occurs when a program runs out of stack space, typically because of too deep recursion. A guard page typically halts the program, preventing memory corruption, but functions with large stack frames may bypass the page.

在C#、Java和Python这样的语言中,内存泄漏与C和C++这样的语言有不同的含义,在C和C++中,你可以手动管理内存。在C或C++中,如果不能重新分配分配内存,就会出现内存泄漏。在有管理内存的语言中,你不必显式地去分配内存,但仍然有可能通过在某个地方意外地保持对内存的引用来做一些很类似的事情。

这实际上是很容易做到的事情,比如说 在C#中的事件处理程序 和长寿命的集合类;事实上,我曾在项目中工作过,尽管我们使用的是托管内存,但还是存在内存泄漏的问题。从某种意义上说,在一个有管理内存的环境中工作,实际上会使这些问题变得更加危险,因为程序员会有一种错误的安全感。根据我的经验,即使是有经验的工程师也经常不做内存剖析或写测试用例来检查这个问题(很可能是由于环境给了他们一种错误的安全感)。

堆栈耗尽在Python中也很容易做到。

    Heap exhaustion - the program tries to allocate more memory than the amount available. In some languages, this condition must be checked for manually after each allocation.

还是很有可能的--我相当尴尬地承认,我个人在C#中做过这样的事情(虽然在Python中还没有)。

    Double free - repeated calls to free may prematurely free a new object at the same address. If the exact address has not been reused, other corruption may occur, especially in allocators that use free lists.
    Invalid free - passing an invalid address to free can corrupt the heap.
    Mismatched free - when multiple allocators are in use, attempting to free memory with a deallocation function of a different allocator[20]
    Unwanted aliasing - when the same memory location is allocated and modified twice for unrelated purposes.

不需要的别名其实在 Python 中很容易做到。这里有一个 例子 (完全公开:我写了被接受的答案);你也可以在 Python 中很容易地做类似的事情。其他的都是由 Python 解释器自己管理的。

所以,看来内存安全是相对的。根据你所认为的 "内存安全问题 "的具体内容,它实际上很难完全防止。像Java、C#和Python这样的高级语言可以防止许多最糟糕的错误,但还有其他一些问题是很难或无法完全防止的。

© www.soinside.com 2019 - 2024. All rights reserved.