← 返回首页
Multiple calls to __del__ during object destruction — CodeQL query help documentation CodeQL docs
CodeQL documentation
CodeQL resources

Multiple calls to __del__ during object destruction

ID: py/multiple-calls-to-delete Kind: problem Security severity: Severity: warning Precision: very-high Tags: - quality - reliability - correctness Query suites: - python-code-quality.qls - python-security-and-quality.qls

Click to see the query in the CodeQL repository

Python, unlike some other object-oriented languages such as Java, allows the developer complete freedom in when and how superclass finalizers are called during object finalization. However, the developer has responsibility for ensuring that objects are properly cleaned up.

Objects with a __del__ method (a finalizer) often hold resources such as file handles that need to be cleaned up. If a superclass finalizer is called multiple times, this may lead to errors such as closing an already closed file, and lead to objects not being cleaned up properly as expected.

There are a number of ways that a __del__ method may be called more than once.

Recommendation

Ensure that each finalizer method is called exactly once during finalization. This can be ensured by calling super().__del__ for each finalizer method in the inheritance chain.

Example

In the following example, there is a mixture of explicit calls to __del__ and calls using super(), resulting in Vehicle.__del__ being called twice. FixedSportsCar.__del__ fixes this by using super() consistently with the other delete methods.

#Calling a method multiple times by using explicit calls when a base uses super() class Vehicle(object): def __del__(self): recycle(self.base_parts) super(Vehicle, self).__del__() class Car(Vehicle): def __del__(self): recycle(self.car_parts) super(Car, self).__del__() class SportsCar(Car, Vehicle): # BAD: Vehicle.__del__ will get called twice def __del__(self): recycle(self.sports_car_parts) Car.__del__(self) Vehicle.__del__(self) # GOOD: super() is used ensuring each del method is called once. class FixedSportsCar(Car, Vehicle): def __del__(self): recycle(self.sports_car_parts) super(SportsCar, self).__del__()

References