From 58659bd77eb080db99a97ff39ec24bfa7334d597 Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Thu, 20 Jan 2022 13:30:34 +0100 Subject: [PATCH] [CP-SAT] fix memory leak in C# --- ortools/init/csharp/init.i | 8 ++++++++ ortools/init/init.h | 9 +++++++++ ortools/util/csharp/proto.i | 7 ++++--- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ortools/init/csharp/init.i b/ortools/init/csharp/init.i index eae221b9c3..96187bdc3a 100644 --- a/ortools/init/csharp/init.i +++ b/ortools/init/csharp/init.i @@ -13,12 +13,19 @@ %include "ortools/base/base.i" +%include "stdint.i" %include "std_string.i" %{ #include "ortools/init/init.h" %} +%typemap(ctype) uint8_t* "uint8_t*" +%typemap(imtype) uint8_t* "System.IntPtr" +%typemap(cstype) uint8_t* "System.IntPtr" +%typemap(csin) uint8_t* "$csinput" +%typemap(in) uint8_t* %{ $1 = $input; %} + %ignoreall %unignore operations_research; @@ -38,6 +45,7 @@ %unignore operations_research::CppBridge::ShutdownLogging; %unignore operations_research::CppBridge::SetFlags; %unignore operations_research::CppBridge::LoadGurobiSharedLibrary; +%unignore operations_research::CppBridge::DeleteByteArray; %unignore operations_research::OrToolsVersion; %unignore operations_research::OrToolsVersion::MajorNumber; diff --git a/ortools/init/init.h b/ortools/init/init.h index c4b34499f8..d9ece64b2f 100644 --- a/ortools/init/init.h +++ b/ortools/init/init.h @@ -14,6 +14,7 @@ #ifndef OR_TOOLS_OPEN_SOURCE_INIT_INIT_H_ #define OR_TOOLS_OPEN_SOURCE_INIT_INIT_H_ +#include #include #include @@ -123,6 +124,14 @@ class CppBridge { static bool LoadGurobiSharedLibrary(const std::string& full_library_path) { return LoadGurobiDynamicLibrary({full_library_path}).ok(); } + + /** + * Delete a temporary C++ byte array. + */ + static void DeleteByteArray(uint8_t* buffer) { + delete [] buffer; + } + }; class OrToolsVersion { diff --git a/ortools/util/csharp/proto.i b/ortools/util/csharp/proto.i index 69708f9e91..7bc1c65dc7 100644 --- a/ortools/util/csharp/proto.i +++ b/ortools/util/csharp/proto.i @@ -76,10 +76,10 @@ %typemap(csout) CppProtoType { System.IntPtr data = $imcall; int size = System.Runtime.InteropServices.Marshal.ReadInt32(data); - data += sizeof(int); + System.IntPtr bufferStart = data + sizeof(int); byte[] buf = System.Buffers.ArrayPool.Shared.Rent(size); - System.Runtime.InteropServices.Marshal.Copy(data, buf, 0, size); - // TODO(user): delete the C++ buffer. + System.Runtime.InteropServices.Marshal.Copy(bufferStart, buf, 0, size); + Google.OrTools.Init.CppBridge.DeleteByteArray(data); try { return CSharpProtoType.Parser.ParseFrom(System.MemoryExtensions.AsSpan(buf, 0, size)); } catch (Google.Protobuf.InvalidProtocolBufferException /*e*/) { @@ -98,4 +98,5 @@ $result[2] = (size >> 16) & 0xFF; $result[3] = (size >> 24) & 0xFF; } + %enddef // end PROTO2_RETURN