2017-05-05 22 views
0

マーク/スイープガベージコレクションアルゴリズムをシミュレートする小さなプログラムを作成しました。ほとんどの場合、私のカスタムis_int()関数は、mem_block->mem_blockの参照との参照を区別するために使用します(pointer_variableの名前は整数にできないため)0が渡されたときにはTrueを返しませんプログラム全体を実行中Python整数型チェック関数の出力が矛盾します

is_int(0)を実行しているPythonインタラクティブモードでこの関数を実行すると、正しくTrueが返されます。しかし、プログラム全体を実行している間に、if is_int(x)/elsex == 0と私が理由を理解できないときに私をelseブランチにダンプします。

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() 

スクリーンショット:

Interactive Mode

ここ

は、最も関連性の高いコードブロックは、「#の問題のコード」と表記されているソースコードと状況を証明するスクリーンショットのカップルであります

Running program with no references from 0th mem_block

機能is_int()

+2

あなたはそれが整数0であり、単一の文字 '' 0 "'の文字列ではないことを確かめますか? –

+0

@IljaEveriläあなたはこれが私が考えた最初のことであったことを知っています。そして、コードを何度も使って問題を引き起こす可能性があることを知りました。 'elif s == 0'を' elif int(s)== 0 'に変更する必要がありました これらの整数が単一の文字列であれば、他の整数EVENでも機能していましたので、その部分が別のステートメントで処理されるため、単一のchar文字列 '0'では機能しません。 – user3776749

答えて

0

、ライン:パラメータはANのいずれかを含む文字列ですので、正しく入力を評価するために

elif int(s) == 0

に変更する必要が

elif s == 0

整数OR変数名がファイルから読み込まれます。これは、ゼロ以外の整数の場合には暗黙的に処理されますが、elifゼロケースで再度実行する必要があります。

+0

'int(s)'が(上がらない場合)*は常にtrueまたはゼロになるので、これは意味をなさない。つまり、あなたの 'is_int'関数全体が' int(s) 'と' return true'の後に続く関数になります。 IOWは、Trueを返すか、入力をintに変換できない場合には例外を送出します。 –

+0

単に 's.isdigit()'を実行したいかもしれません(負の整数を扱う必要がないと仮定します)。 –

+0

@ MarkDickinsonええ、私は 'ValueError:return False'を除いてintを返すような別のバージョンの関数を持っていましたが、' s == 0'の場合は関数int() Pythonは 'False'と見なします。この場合、' True'と評価する必要があります。 'isdigit'は複数の桁の文字列、すなわち' s == "1234" 'に対して機能するでしょうか? – user3776749

関連する問題