#! /usr/bin/env python #----------------------------------------------------------------------------- # Copyright (c) 2021, 2022, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #----------------------------------------------------------------------------- """ A script to help identify memory leaks. The script argument should be the name of a file containing the trace output when DPI_DEBUG_LEVEL is set to DPI_DEBUG_LEVEL_MEM (32): export DPI_DEBUG_LEVEL=32 ./myprog >& mem.log python mem_leak.py mem.log """ import sys ALLOCATED_STRING = ": allocated " FREED_STRING = ": freed " OCI_ALLOCATED_STRING = ": OCI allocated " OCI_FREED_STRING = ": OCI freed " def check_memory_use(file_name): """ Checks memory use found in the given file. This file is assumed to have been generated by setting DPI_DEBUG_LEVEL to the value 32. """ memory_locations = {} for line in open(file_name): # check for ODPI-C allocation pos = line.find(ALLOCATED_STRING) if pos > 0: parts = line[pos + len(ALLOCATED_STRING):].split() size = int(parts[0]) memory_location = parts[3] memory_locations.setdefault(memory_location, []).append(size) continue # check for ODPI-C free pos = line.find(FREED_STRING) if pos > 0: parts = line[pos + len(FREED_STRING):].split() memory_location = parts[2] memory_locations[memory_location].pop(0) if not memory_locations[memory_location]: del memory_locations[memory_location] continue # check for OCI allocation pos = line.find(OCI_ALLOCATED_STRING) if pos > 0: parts = line[pos + len(OCI_ALLOCATED_STRING):].split() size = int(parts[0]) memory_location = parts[3] memory_locations.setdefault(memory_location, []).append(size) continue # check for OCI free pos = line.find(OCI_FREED_STRING) if pos > 0: parts = line[pos + len(OCI_FREED_STRING):].split() memory_location = parts[2] memory_locations[memory_location].pop(0) if not memory_locations[memory_location]: del memory_locations[memory_location] continue print("Potential Memory Leaks") for memory_location in memory_locations: print(memory_location, "-> size", sum(memory_locations[memory_location])) check_memory_use(sys.argv[1])