Skip to content

Commit d8a7b6a

Browse files
authored
fix #1358 (#1359)
1 parent ba8f814 commit d8a7b6a

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

src/Core/Silk.NET.Core/Native/GlobalMemory.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ public sealed class GlobalMemory : IDisposable
1414
{
1515
// Actual object
1616
private readonly object _memoryObject;
17+
private int _stringArrayCount;
18+
private bool _freed = false;
1719

18-
private GlobalMemory(object memoryObject, int length)
20+
private GlobalMemory(object memoryObject, int length, int stringArrayCount = 0)
1921
{
2022
_memoryObject = memoryObject;
2123
Length = length;
24+
_stringArrayCount = stringArrayCount;
2225
}
2326

2427
/// <summary>
@@ -120,6 +123,17 @@ public unsafe ref byte GetPinnableReference()
120123

121124
private unsafe void Free()
122125
{
126+
if (_stringArrayCount != 0)
127+
{
128+
var span = AsSpan<IntPtr>();
129+
for (var index = 0; index < _stringArrayCount; index++)
130+
{
131+
var intPtr = span[index];
132+
SilkMarshal.Free(intPtr);
133+
}
134+
135+
_stringArrayCount = 0;
136+
}
123137
switch (_memoryObject)
124138
{
125139
case HGlobal hGlobal:
@@ -145,6 +159,8 @@ private unsafe void Free()
145159
}
146160
#endif
147161
}
162+
163+
_freed = true;
148164
}
149165

150166
/// <inheritdoc />
@@ -174,6 +190,15 @@ public static GlobalMemory Allocate(int length) =>
174190
new GlobalMemory(new GCHandleByteArray(length), length > 0 ? length : 1);
175191
#endif
176192

193+
internal static GlobalMemory AllocateForStringArray(int length, int count) =>
194+
#if NET6_0_OR_GREATER
195+
new GlobalMemory(new NativeMemoryPtr(length), length > 0 ? length : 1, count);
196+
#elif NET5_0
197+
new GlobalMemory(GC.AllocateUninitializedArray<byte>(length > 0 ? length : 1, true), length, count);
198+
#else
199+
new GlobalMemory(new GCHandleByteArray(length), length > 0 ? length : 1, count);
200+
#endif
201+
177202
// Encapsulations different kinds of memory
178203
private interface IGlobalMemory
179204
{

src/Core/Silk.NET.Core/Native/SilkMarshal.cs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ static SilkMarshal()
5353
// This means that the GlobalMemory is only freed when the user calls Free.
5454
private static readonly ConcurrentDictionary<nint, GlobalMemory> _marshalledMemory = new();
5555

56-
// In addition, we should keep track of the memory we allocate dedicated to string arrays. If we don't, we won't
57-
// know to free the individual strings allocated within memory.
58-
private static readonly ConcurrentDictionary<GlobalMemory, int> _stringArrays = new();
59-
6056
// Other kinds of GCHandle-pinned pointers may be passed into Free, like delegate pointers for example which
6157
// must have GCHandles allocated on older runtimes to avoid an ExecutionEngineException.
6258
// We should keep track of those.
@@ -96,15 +92,6 @@ public static bool Free(nint ptr)
9692
return ret;
9793
}
9894

99-
if (_stringArrays.TryRemove(val, out var numStrings))
100-
{
101-
var span = val.AsSpan<nint>();
102-
for (var i = 0; i < numStrings; i++)
103-
{
104-
Free(span[i]);
105-
}
106-
}
107-
10895
val.Dispose();
10996
return ret;
11097
}
@@ -364,7 +351,7 @@ public static GlobalMemory StringArrayToMemory
364351
NativeStringEncoding e = NativeStringEncoding.Ansi
365352
)
366353
{
367-
var memory = GlobalMemory.Allocate(input.Count * IntPtr.Size);
354+
var memory = GlobalMemory.AllocateForStringArray(input.Count * IntPtr.Size, input.Count);
368355
var span = memory.AsSpan<nint>();
369356
for (var i = 0; i < input.Count; i++)
370357
{
@@ -386,7 +373,7 @@ public static GlobalMemory StringArrayToMemory
386373
Func<string, nint> customStringMarshaller
387374
)
388375
{
389-
var memory = GlobalMemory.Allocate(input.Count * IntPtr.Size);
376+
var memory = GlobalMemory.AllocateForStringArray(input.Count * IntPtr.Size, input.Count);
390377
var span = memory.AsSpan<nint>();
391378
for (var i = 0; i < input.Count; i++)
392379
{
@@ -409,7 +396,6 @@ public static nint StringArrayToPtr
409396
)
410397
{
411398
var memory = StringArrayToMemory(input, encoding);
412-
_stringArrays.TryAdd(memory, input.Count);
413399
return RegisterMemory(memory);
414400
}
415401

@@ -426,7 +412,6 @@ Func<string, nint> customStringMarshaller
426412
)
427413
{
428414
var memory = StringArrayToMemory(input, customStringMarshaller);
429-
_stringArrays.TryAdd(memory, input.Count);
430415
return RegisterMemory(memory);
431416
}
432417

0 commit comments

Comments
 (0)