我創建了一個模擬標記/掃描垃圾收集算法的小程序。大多數情況下,它的工作原理完全只有一個例外:我用於區分10和pointer_variable->mem_block
(因爲pointer_variable
名稱不能是整數)的引用的自定義is_int()
函數在傳遞0
時無法返回True
運行整個程序Python整數類型檢查函數輸出不一致
當我在Python交互模式下運行is_int(0)
運行功能,而正確返回True
。但是,在運行整個程序時,if is_int(x)/else
會將我轉入else分支,因此x == 0
和我無法弄清楚原因。
這裏是源代碼和一些截圖展示的局面,最相關的代碼塊被標以「#問題代碼」:
import argparse
import re
import sys
class MemoryObject():
def __init__(self):
self.marked = 0
self.references = [] # list of <MemoryObject> references
def arg_parse():
# Sets up a parser object for handling arguments passed to the program
parser = argparse.ArgumentParser(description='Some description')
parser.add_argument('filename', help='Filename parameter for input file')
return parser.parse_args()
# PROBLEM CODE
def is_int(s):
# Determines if the given variable contains only an integer value
# Primarily used to distinguish memory-blocks from named
# pointer variables
if int(s):
return True
elif s == 0:
return True
else:
return False
# /PROBLEM CODE
def node_trace(current_node, node_dict):
# This function recursively simulates the "mark" phase of
# Mark/Sweep G.C. using a dictionary of <MemoryObject>
# each element therin containing its list of references
#
# Each node traversed is marked, and the function returns
# if the node has already been checked
#
# This function assumed the inital call was passed the RootMemoryBlock
# as it's starting point, which garuntees only accessible memory will
# be marked since RootMemoryBlock only references pointers which
# in turn, by definition, only reference chains of accessible memory
if current_node.marked == 1:
return
else:
current_node.marked = 1
for node in current_node.references:
node_trace(node, node_dict)
def get_nodes():
# This function creates a dictionary of memory-blocks and named
# pointer-variables ncluding a "RootMemoryBlock" that hold the
# pointer-variables. The number of memory blocks/variables is
# determined by the contents of the input file.
#
# Each object is stored in the dictionary as a <MemoryObject>
#
# The contents of the input file are then used to determine all references
# between variables->blocks and blocks->blocks, with the only object
# referencing named-variables being the RootMemoryBlock. The format
# of the file garuntees that memory_blocks are listed as integers, and
# variables as strings that start with either a letter or an underscore '_'
#
# is_int is therefor used to determing if an object is a variable or a
# memory-block when populating the reference lists for the elements
# of the <MemoryObject> dictionary
#
# Each object's reference list is stored in its <MemoryObject>::references
# as a list of references to <MemoryObject>
#
# The dictionary is then passed into the node_trace function along with the
# RootMemoryBlock <MemoryObject> which recursively performs the
# "mark" phase of Mark/Sweep G.C.
#
# Finally a new dictionary is created and JUST the info for the
# memory-blocks (not variables, or the RootBlock) is copied into it.
#
# That dictionary is then returned to the calling function.
node_pointers = []
node_dict = {}
args = arg_parse()
input_file = args.filename
with open(input_file) as in_file:
node_count = 0
for line in in_file:
if node_count == 0:
node_count = int(line)
else:
split_line = line.rstrip()
split_line = re.split(r'[,]', split_line)
node_pointers.append([split_line[0], int(split_line[1])])
root_node_key = node_count
array_size = node_count + 1
for i in range (array_size):
node_dict[i] = MemoryObject()
# The format of the input file garuntees that each item will
# describe a link of the form [source, target]
SOURCE = 0 # The source of a reference link
TARGET = 1 # The target of a reference link
for item in node_pointers:
# PROBLEM CODE
if is_int(item[SOURCE]):
node_dict[int(item[SOURCE])].references.append(node_dict[item[TARGET]])
else:
if item[SOURCE] not in node_dict.keys():
node_dict[item[SOURCE]] = MemoryObject()
node_dict[item[SOURCE]].references.append(node_dict[item[TARGET]])
node_dict[root_node_key].references.append(node_dict[item[SOURCE]])
# /PROBLEM CODE
node_trace(node_dict[root_node_key], node_dict)
node_dict_final = {}
for element in node_dict.keys():
if is_int(element) and element != root_node_key:
node_dict_final[element] = node_dict[element]
return node_dict_final
def print_result(message, value, nodes):
# Displays the results of the mark/sweep algorithm
# as stored in the dictionary "nodes"
#
# Prints all marked nodes if value == 1
# Prints all reclaimed nodes if value == 0
print(message)
for element in nodes.items():
if element[1].marked == value:
if is_int(element[0]):
print(element[0])
def main():
# Entry Point function. Calls get_nodes which processes
# the input_file, then runs the simluated mark/sweep
# algorithm.
#
# It then displays the returned results of the mark/sweep
nodes = get_nodes()
print_result('\nMarked: ', 1, nodes)
print_result('\nReclaimed: ', 0, nodes)
print()
if __name__ == '__main__':
main()
截圖:
Running program with no references from 0th mem_block
Running program with references from 0th mem_block
你確定它是整數0而不是一個單一的字符串'「0」'? –
@IljaEverilä你知道這是我想到的第一件事,我多次瀏覽了代碼,試圖瞭解這可能會導致問題無濟於事,只是現在才知道爲什麼/如何。 我需要將'elif s == 0'改爲'elif int(s)== 0' 由於該函數可以用於任何其他整數EVEN,如果這些整數是單個字符串,我沒有注意到它將不會使用單個字符串「0」,因爲該部分是在不同的語句中處理的。 – user3776749