dkprojektai 1 Posted May 13, 2019 Hello, I have a memory leak (EurekaLog): Memory Leak: Type=UnicodeString: Ref count - 1, Content: "Archive info"; Total size=78; Count=3; It happens not every time. It found in: var result_text: IRecognitionResult; procedure TWorkerThread.Execute; begin ... OtlParallel.Parallel.For(0, 20,1).NumTasks(6).Execute( procedure (value: integer) var Recognition: string; begin ... Locking.EnterWriteLock; Try Recognition:= result_text.recognition_text >>>>> here is leak Finally Locking.ExitWriteLock; End; .... end); ... end; IRecognitionResult = interface(IDispatch) .... function Get_text: String; safecall; property recognition_text: String read Get_text; end; Can somebody explain how to avoid this? I have tried to change line to this: Recognition := Copy(result_text.recognition_text,1,Pos(#0,result_text.recognition_text)-1) because dll returns info like "Archive info#0aaa,bf;ddf...", but it does not help. Thanks. Share this post Link to post
David Heffernan 2345 Posted May 13, 2019 A complete reproduction is surely needed here. As an aside, can't you use a read lock here? Share this post Link to post
dkprojektai 1 Posted May 13, 2019 allocation number: 1804277 program up time: 3:04 min type: UnicodeString address: $da9db60 size: 26 access rights: read/write code page: 1200 reference counter: 1 string length: 6 contents: Detected text thread $85e8 (TOTPWorkerThread): 671a52b3 madExcept32.dll madExceptDbg 1736 GetMemCallback 004073e8 Main_program.exe System 4758 @GetMem 0040bd86 Main_program.exe System 24650 @NewUnicodeString 0040bfb7 Main_program.exe System 25328 @UStrFromPWCharLen01268b1f Main_program.exe Unit1 14371 TWorkerThread.Execute$ActRec.$2$Body 0118353a Main_program.exe OtlParallel 3440 TOmniParallelSimpleLoop.Execute[2]$ActRec.$0$Body 01183054 Main_program.exe OtlParallel 3380 TOmniParallelSimpleLoop.CreateForTask$ActRec.$0$Body 0115b76f Main_program.exe OtlTaskControl 1991 TOmniTaskExecutor.Asy_Execute 0115a51e Main_program.exe OtlTaskControl 1584 TOmniTask.InternalExecute 0040a038 Main_program.exe System 17320 TObject.GetInterface 0040a081 Main_program.exe System 17327 TObject.GetInterface 00411d3b Main_program.exe System 38375 TInterfacedObject.QueryInterface 00410916 Main_program.exe System 37361 @IntfCast 0115a248 Main_program.exe OtlTaskControl 1502 TOmniTask.Execute 0114c624 Main_program.exe OtlThreadPool 889 TOTPWorkerThread.ExecuteWorkItem 0114c800 Main_program.exe OtlThreadPool 918 TOTPWorkerThread.GetMsg 0114c19f Main_program.exe OtlThreadPool 846 TOTPWorkerThread.Execute 004adbb7 Main_program.exe madExcept HookedTThreadExecute 0053ca51 Main_program.exe System.Classes 14945 ThreadProc 0040bcd4 Main_program.exe System 24423 ThreadWrapper 004ada9d Main_program.exe madExcept CallThreadProcSafe 004adb02 Main_program.exe madExcept ThreadExceptFrame 755e0417 KERNEL32.DLL BaseThreadInitThunk I quess - convertion from widestring to string is the problem. But how to fix it? Share this post Link to post
David Heffernan 2345 Posted May 13, 2019 Before knowing how to fix it, you need to know what causes the leak. That's where the minimal reproduction comes in. Share this post Link to post
dkprojektai 1 Posted May 13, 2019 I'm now trying on - Finalize(result_text); Leak detectors does not register leaks. Will write if it will help... Share this post Link to post
Remy Lebeau 1399 Posted May 14, 2019 (edited) String is not an automation compatible data type. The IRecognitionResult.Get_text() method and IRecognition.recognition_text property need to be declared to use WideString instead of String. IRecognitionResult = interface(IDispatch) function Get_text: WideString; safecall; property recognition_text: WideString read Get_text; end; Edited May 14, 2019 by Remy Lebeau 1 Share this post Link to post
dkprojektai 1 Posted January 9, 2020 Locking.EnterWriteLock; Try Recognition:= String(result_text.recognition_text); Finally Locking.ExitWriteLock; End; Remy - am I understand correctly? I should do like this? Share this post Link to post
Remy Lebeau 1399 Posted January 12, 2020 On 1/9/2020 at 2:19 PM, dkprojektai said: Locking.EnterWriteLock; Try Recognition:= String(result_text.recognition_text); Finally Locking.ExitWriteLock; End; Remy - am I understand correctly? I should do like this? That type-cast is not necessary. Assigning a String (or a WideString) to a String is handled automatically by the compiler. This is not the source of your leaking. Did you change the recognition_text property to return a WideString instead of a String, like I suggested 8 months ago? What does the implementation of Get_text() actually look like? 1 Share this post Link to post
dkprojektai 1 Posted January 13, 2020 I can't change it - it's from third library Share this post Link to post
A.M. Hoornweg 144 Posted January 13, 2020 3 hours ago, dkprojektai said: I can't change it - it's from third library Library, as in DLL? You really can't pass a "string" from a DLL to an application, except when both projects are configured to use a shared memory manager ("uses sharemem"). Share this post Link to post
David Heffernan 2345 Posted January 13, 2020 That reproduction is still required Share this post Link to post
Remy Lebeau 1399 Posted January 14, 2020 On 1/12/2020 at 8:58 PM, dkprojektai said: I can't change it - it's from third library Then you are going to have to ask the library author to change it, because this implementation is broken. IRecognitionResult is derived from IDispatch, which is an OLE interface. Pascal strings simply are not compatible with OLE - period. The Pascal wrapper for the interface MUST use WideString instead, which uses the OLE BSTR string type. 1 Share this post Link to post
dkprojektai 1 Posted January 14, 2020 I'm very sorry. I double check. The IRecognitionResult is: property recognition_text: WideString read Get_text; Should I somehow transform Recognition: string; into WideString? Share this post Link to post
David Heffernan 2345 Posted January 14, 2020 7 minutes ago, dkprojektai said: I'm very sorry. I double check. The IRecognitionResult is: property recognition_text: WideString read Get_text; Should I somehow transform Recognition: string; into WideString? If you want to solve a problem, the first step is to understand it fully. Guesswork is unlikely to be successful. If you want help from others, help them to be able to reproduce the issue. Share this post Link to post
dkprojektai 1 Posted January 14, 2020 2 minutes ago, David Heffernan said: If you want to solve a problem, the first step is to understand it fully. Guesswork is unlikely to be successful. If you want help from others, help them to be able to reproduce the issue. sorry, I can't crop some lines and make example from 15000 lines of code with treading and third party libraries. Share this post Link to post
David Heffernan 2345 Posted January 14, 2020 50 minutes ago, dkprojektai said: sorry, I can't crop some lines and make example from 15000 lines of code with treading and third party libraries. Then you'll have to debug this yourself. Share this post Link to post
Remy Lebeau 1399 Posted January 15, 2020 20 hours ago, dkprojektai said: I'm very sorry. I double check. The IRecognitionResult is: property recognition_text: WideString read Get_text; Then I don't see how there can possibly be a leak in the code you have shown. Something else is going on. You are just going to have to debug the code for yourself to see exactly where the real leak is. What you described earlier suggests that the compiler is not freeing the 'Recognition: string' variable when your Parallel.For() procedure exits, and that is simply not how the compiler is supposed to work. 20 hours ago, dkprojektai said: Should I somehow transform Recognition: string; into WideString? That is not necessary. As I stated earlier, you can assign a WideString directly to a String, and vice versa. The compiler will handle everything for you, as WideString and String are both managed types that the compiler knows how to convert between, and free when they go out of scope. Share this post Link to post