From 057e025ee37010b93d42d6706c86f9a87612b211 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 10 Dec 2015 00:47:25 +0200 Subject: [PATCH] Fixed a memory leak by removing from static members typedefs used for delegates. Signed-off-by: Dimitar Dobrev --- src/Generator/Driver.cs | 6 +- .../Generators/CSharp/CSharpTextTemplate.cs | 16 ++++- src/Generator/Passes/DelegatesPass.cs | 72 +++++++++++++------ 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index 86cf072e..db0e4e93 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -14,6 +14,7 @@ using CppSharp.Types; using Microsoft.CSharp; using CppSharp.Parser; using System.CodeDom; +using System; namespace CppSharp { @@ -32,6 +33,8 @@ namespace CppSharp public ASTContext ASTContext { get; private set; } public SymbolContext Symbols { get; private set; } + public Dictionary Delegates { get; private set; } + public bool HasCompilationErrors { get; set; } private static readonly Dictionary libraryMappings = new Dictionary(); @@ -43,6 +46,7 @@ namespace CppSharp Project = new Project(); ASTContext = new ASTContext(); Symbols = new SymbolContext(); + Delegates = new Dictionary(); TypeDatabase = new TypeMapDatabase(); TranslationUnitPasses = new PassBuilder(this); GeneratorOutputPasses = new PassBuilder(this); @@ -429,7 +433,7 @@ namespace CppSharp GeneratorOutputPasses.AddPass(pass); } - private List compileUnits = new List(); + private readonly List compileUnits = new List(); } public static class ConsoleDriver diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index 7ac8d4b4..33a4e9c7 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -1573,7 +1573,7 @@ namespace CppSharp.Generators.CSharp var vTableMethodDelegateName = GetVTableMethodDelegateName(method); - WriteLine("private static {0} {1}Instance;", DelegatesPass.Delegates[method].Visit(TypePrinter), + WriteLine("private static {0} {1}Instance;", GetDelegateName(Driver.Delegates[method]), vTableMethodDelegateName); NewLine(); @@ -2355,7 +2355,7 @@ namespace CppSharp.Generators.CSharp } } - public void GetVirtualCallDelegate(Method method, Class @class, + private void GetVirtualCallDelegate(Method method, Class @class, out string delegateId) { var i = VTables.GetVTableIndex(method.OriginalFunction ?? method, @class); @@ -2371,7 +2371,17 @@ namespace CppSharp.Generators.CSharp delegateId = Generator.GeneratedIdentifier(@delegate); WriteLine("var {0} = ({1}) Marshal.GetDelegateForFunctionPointer(new IntPtr({2}), typeof({1}));", - delegateId, DelegatesPass.Delegates[method].Visit(TypePrinter), Helpers.SlotIdentifier); + delegateId, GetDelegateName(Driver.Delegates[method]), Helpers.SlotIdentifier); + } + + private string GetDelegateName(DelegatesPass.DelegateDefinition @delegate) + { + if (string.IsNullOrWhiteSpace(@delegate.Namespace) || + Driver.Options.OutputNamespace == @delegate.Namespace) + { + return @delegate.Signature; + } + return string.Format("{0}.{1}", @delegate.Namespace, @delegate.Signature); } private void GenerateOperator(Method method) diff --git a/src/Generator/Passes/DelegatesPass.cs b/src/Generator/Passes/DelegatesPass.cs index b93c2332..a15cdbfd 100644 --- a/src/Generator/Passes/DelegatesPass.cs +++ b/src/Generator/Passes/DelegatesPass.cs @@ -4,6 +4,7 @@ using System.Text; using CppSharp.AST; using CppSharp.AST.Extensions; using CppSharp.Generators.CSharp; +using System; namespace CppSharp.Passes { @@ -11,6 +12,19 @@ namespace CppSharp.Passes { public const string DelegatesNamespace = "Delegates"; + public class DelegateDefinition + { + public DelegateDefinition(string @namespace, string signature) + { + Namespace = @namespace; + Signature = signature; + } + + public string Namespace { get; private set; } + + public string Signature { get; private set; } + } + public DelegatesPass() { Options.VisitClassBases = false; @@ -21,15 +35,10 @@ namespace CppSharp.Passes Options.VisitTemplateArguments = false; } - public static Dictionary Delegates - { - get { return delegates; } - } - public override bool VisitLibrary(ASTContext context) { foreach (var library in Driver.Options.Libraries.Where(l => !libsDelegates.ContainsKey(l))) - libsDelegates.Add(library, new Dictionary()); + libsDelegates.Add(library, new Dictionary()); var unit = context.TranslationUnits.Last(u => u.IsValid && u.IsGenerated && !u.IsSystemHeader && u.HasDeclarations); @@ -50,12 +59,6 @@ namespace CppSharp.Passes var @params = method.GatherInternalParams(Driver.Options.IsItaniumLikeAbi, true).ToList(); var delegateName = GenerateDelegateSignature(@params, method.ReturnType); - var existingDelegate = GetExistingDelegate(delegateName); - if (existingDelegate != null) - { - delegates.Add(method, existingDelegate); - return true; - } var @delegate = new TypedefDecl { @@ -72,24 +75,35 @@ namespace CppSharp.Passes }))), Namespace = namespaceDelegates }; - delegates.Add(method, @delegate); + + var delegateString = @delegate.Visit(TypePrinter).Type; + var existingDelegate = GetExistingDelegate(delegateString); + if (existingDelegate != null) + { + Driver.Delegates.Add(method, existingDelegate); + return true; + } + + existingDelegate = new DelegateDefinition(Driver.Options.OutputNamespace, delegateString); + Driver.Delegates.Add(method, existingDelegate); foreach (var library in Driver.Options.Libraries) - libsDelegates[library].Add(delegateName, @delegate); + libsDelegates[library].Add(delegateString, existingDelegate); namespaceDelegates.Declarations.Add(@delegate); return true; } - private TypedefDecl GetExistingDelegate(string delegateName) + private DelegateDefinition GetExistingDelegate(string delegateString) { - TypedefDecl @delegate = null; - if (Driver.Options.Libraries.Count == 0) - return @delegates.Values.FirstOrDefault(v => v.Name == delegateName); + return Driver.Delegates.Values.FirstOrDefault(t => t.Signature == delegateString); - if (Driver.Options.Libraries.Union(Driver.Symbols.Libraries.SelectMany(l => l.Dependencies)).Any( - l => libsDelegates.ContainsKey(l) && libsDelegates[l].TryGetValue(delegateName, out @delegate))) + DelegateDefinition @delegate = null; + if (Driver.Options.Libraries.Union( + Driver.Symbols.Libraries.SelectMany(l => l.Dependencies)).Any( + l => libsDelegates.ContainsKey(l) && + libsDelegates[l].TryGetValue(delegateString, out @delegate))) return @delegate; return null; @@ -124,8 +138,22 @@ namespace CppSharp.Passes return delegateName; } + private CSharpTypePrinter TypePrinter + { + get + { + if (typePrinter == null) + { + typePrinter = new CSharpTypePrinter(Driver); + typePrinter.PushContext(CSharpTypePrinterContextKind.Native); + } + return typePrinter; + } + } + private Namespace namespaceDelegates; - private static readonly Dictionary> libsDelegates = new Dictionary>(); - private static readonly Dictionary delegates = new Dictionary(); + private CSharpTypePrinter typePrinter; + private static readonly Dictionary> libsDelegates = + new Dictionary>(); } }