If I declare
PSomeStruct = ^TSomeStruct;
TSomeStruct = record
s1 : string;
end;
and I run the following code:
var
p: PSomeStruct;
begin
new(p);
p^.s1:= 'something bla bla bla';
dispose(p);
the FastMM 4 memory manager reports that there was a memory leak (type: string, data dump: "something bla bla bla"). However, if I do set the s1 string to empty before calling dispose it's OK.
The second way I found is to change from record type to class, then instead of new I'm creating the instance, and instead of dispose I'm calling instance.Free(). It works without manually cleaning the strings.
Is there a way to make Delphi automatically clean my strings when I call dispose?
Is FastMM the first unit used in your .dpr? Otherwise it could be finalized too early, reporting false memoryleaks.
And does this simplified codesample also generate the same memoryleak as when you use your JvSimpleXML? When it's not, there is probably more going on then you suspect.
In my opinion: when FastMM reports a memory leak, there is a memoryleak.
You are already doing the correct thing. If FastMM says that string has leaked, then FastMM is wrong, or it's reporting a different string from the one you think it is. The Dispose procedure releases strings from records.
In this particular case, there shouldn't have been any memory allocated for that string anyway. It's a string literal, so I'd expect the compiler to assign that literal; its reference count should be -1 and FastMM never should have seen it.
Related
I'm using openCV with Go and have this function:
func ConvertMatToSlice(c_Mat *CMatrix) []float32 {
c_output := C.Convert(c_Mat.CType)
h := &reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(c_output.val)),
Len: int(c_output.length),
Cap: int(c_output.length),
}
return *(*[]float32)(unsafe.Pointer(h))
}
When I run go vet ./... it gives me:
opencv_wrapper.go:31:7: unsafeptr: possible misuse of reflect.SliceHeader (govet)
h := &reflect.SliceHeader{
^
Is there any other way to get the slice because I'm sure go-vet has its reasons to complain about this.
See Go Issue #40701. A safer alternative would be the following:
func ConvertMatToSlice(c_Mat *CMatrix) []float32 {
c_output := C.Convert(c_Mat.CType)
result := make([]float32, c_output.length)
sh := (*reflect.SliceHeader)(unsafe.Pointer(&result))
sh.Data = uintptr(unsafe.Pointer(c_output.val))
return result
}
I've made a test program mocking the behaviour of your code without using cgo. So let's place it in a directory and do some escape analysis with go build -gcflags "-m -m".
What we're interested is making sure that the slice (slice header) we return is allocated on the heap, and that so is the pointer which it points to in the Data field. As we can see from the escape analysis, b escapes and so does the slice allocation:
./main.go:10:6: b escapes to heap:
./main.go:10:6: flow: {storage for &Output literal} = &b:
./main.go:10:6: from &b (address-of) at ./main.go:17:38
[...]
./main.go:25:16: make([]float32, c_output.length) escapes to heap:
./main.go:25:16: flow: {heap} = &{storage for make([]float32, c_output.length)}:
./main.go:25:16: from make([]float32, c_output.length) (non-constant size) at ./main.go:25:16
In your case, you'll have to make sure yourself from the C code that the pointer is allocated on the heap.
In general, the rule that can be taken from the discussion on the Go issue I've referenced is to never create SliceHeaders yourself. They might work but they can and will lead to memory corruption, creating difficult and hard-to-debug situations in your code. If you do need to get access to a slice yourself, do so either by using make or by using reflect.MakeSlice which are guaranteed to work and will cooperate with the GC properly, and then make the necessary changes to the slice header.
I have to access several functions of a DLL written in c from Delphi (currently Delphi7).
I can do it without problems when the parameters are scalar
(thanks to the examples found in this great site!), but I have been stuck for some time when in the parameters there is a pointer to an array of Longs.
This is the definition in the header file of one of the functions:
BOOL __stdcall BdcValida (HANDLE h, LPLONG opcl);
(opcl is an array of longs)
And this is a portion of my Delphi code:
type
TListaOpciones= array of LongInt; //I tried with static array too!
Popcion = ^LongInt; //tried with integer, Cardinal, word...
var
dllFunction: function(h:tHandle; opciones:Popcion):boolean;stdcall;
arrayOPciones:TListaOpciones;
resultado:boolean;
begin
.....
I give values to aHandle and array arrayOPciones
.....
resultado:=dllFunction(aHandle, #arrayopciones[0]);
end;
The error message when executing it is:
"Project xxx raised too many consecutive exceptions: access violation
at 0x000 .."
What is the equivalent in Delhpi for LPLONG? Or am I calling the function in an incorrect way?
Thank you!
LONG maps to Longint, and LPLONG maps to ^Longint. So, you have translated that type correctly.
You have translated BOOL incorrectly though. It should be BOOL or LongBool in Delphi. You can use either, the former is an alias for the latter.
Your error lies in code or detail we can't see. Perhaps you didn't allocate an array. Perhaps the array is incorrectly sized. Perhaps the handle is not valid. Perhaps earlier calls to the DLL failed to check for errors.
There is something I don't get, please enlighten me.
Is there a difference between the following (client side code)?
1) blah = (const char *)"dummy";
2) blah = CORBA::string_dup("dummy");
... just googling a bit I see string_dup() returns a char * so the 2 may be equivalent.
I was thinking 2) does 2 deep copies and not 1.
I'm firing the question anyway now, please briefly confirm.
Thanks!
const char* blah = "dummy";
The C++ compiler generates a constant array of characters, null-terminated, somewhere in a data section of your executable. blah gets a pointer to it.
char* blah = CORBA::string_dup("dummy");
The function string_dup() is called with an argument that is a pointer to that constant array of characters. string_dup() then allocates memory from the free store and copies the string data into the free-store-allocated memory. The pointer to the free-store memory is returned to the caller. It is the caller's job to dispose of the memory when finished with CORBA::string_free(). Technically the ORB implementation is allowed to use some special free-store, but most likely it is just using the standard heap / free-store that the rest of your application is using.
It is often much better to do this:
CORBA::String_var s = CORBA::string_dup("dummy");
The String_var's destructor will automatically call string_free() when s goes out of scope.
I'm using protobuf inside nif function (erlang nif) and need to create resource of protobuf message type. I wrote something like this:
ERL_NIF_TERM create_resource(ErlNifEnv *env, const MyClass &msg)
{
size_t size = sizeof(MyClass);
MyClass *class = (MyClass *)enif_alloc_resource(MY_CLASS, size);
memcpy(class, &msg, size);
// class->CopyFrom(&msg);
ERL_NIF_TERM term = enif_make_resource(env, class);
enif_release_resource(class);
return term;
}
The question is.. is it legal for the protobuf message to be copied like this and in cleanup just release it with:
delete pointer
?
Seems that everything is right here, but I'm not shure, cause the constructor of the copied object was not invoked and may be there is some magick with static vars and etc...
Also.. do I need to call CopyFrom after memcpy?
upd: MyClass is C++ class not C
enif_alloc_resource, enif_release_resource, and enif_make_resource do all the memory management for you. You can make it somewhat easier by making your resource type a pointer, in which case you call delete from your defined resource destructor (the function pointer you pass when calling enif_open_resource_type).
As far as what you're doing with memcpy, it's not safe for complex objects. For instance, if one of your class members is a pointer to a dynamically allocated resource which it destroys in its destructor, and you memcpy it, two objects are now sharing that same resource. When one of the objects is destroyed (falling out of scope, delete operator), the other object is left with a pointer to freed memory.
This is why you define copy and assignment constructors if you have a complex class. I'm guessing CopyFrom should, in fact, be both your assignment and copy constructor.
I've got some code that worked fine under Delphi 2007 but breaks under D2010. It involves passing in a string, converting it to a PWideChar (specifically, a WideString pointer, not a UnicodeString pointer), doing some processing, and then calling SysFreeString on it. It works fine until a blank string is passed in, then SysFreeString breaks. It calls a bunch of things that end up raising an Int 3 breakpoint inside NTDLL.DLL. Continuing past this point results in
Project raised exception class
$C0000005 with message 'access
violation at 0x7747206e: read of
address 0x539b8dba'.
Which, if you look closely, is not the standard Access Violation message.
The top of the stack trace when it hits the Int 3 looks like this:
:774e475d ; ntdll.dll
:774afad0 ; ntdll.dll
:774e5de9 ; ntdll.dll
:774a6dff ; ntdll.dll
:76fc1075 ; C:\Windows\system32\ole32.dll
:770e443a ; C:\Windows\system32\oleaut32.dll
:770e3ea3 oleaut32.SysFreeString + 0x4a
Does anyone have any idea what's going on here?
Edit (from the comments):
This isn't a WideString, though. It's
a PWideChar generated by
StringToOleStr, and there are no
double-free errors when a non-blank
string is passed in. Unfortunately, I
can't really post a code sample
because this is a third-party
component that's under copyright. (And
I can't ask them for support because
it's no longer supported. Basically,
the whole thing's one big mess.)
I'm going to try psychic debugging. You've got some kind of heap corruption in your application and SysFreeString is the unfortunate victim (it's hard to tell without OS symbols, you should probably install the MSFT symbol packages for your OS).
Try enabling application verifier (in particular pageheap) for your app and see if it crashes earlier.
It is hard to diagnose without seeing your actual code, however WideString automatically calls SysFreeString() when it goes out of scope. It sounds like your code may be making a second call to SysFreeString() on memory that has already been freed. WideString itself has not changed at all between D2007 and D2010, but other aspects of Delphi's string handling have. Maybe you are not managing the strings correctly. Can you please show your actual code?
A simple test shows that you need to be really careful on what you do in which order.
So: even though you cannot post a small example, can you indicate what you are doing in a bit more detail?
Bad debugging; ignore the things below; see comment.
The SysFreeString() is being called at the end of the the Allocate() call, even though it returns a PWideChar:
program ShowStringToOleStrBehaviourProject;
{$APPTYPE CONSOLE}
uses
SysUtils;
function Allocate(const Value: UnicodeString): PWideChar;
begin
Result := StringToOleStr(Value);
// implicit SysFreeString(WideChars);
end;
procedure Run;
var
WideChars: PWideChar;
begin
WideChars := Allocate('Foo');
Writeln(WideChars);
end;
begin
try
Run();
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Note the console still outputs 'Foo' because the memory has not been overwritten yet.
--jeroen
It can be different reasons of such kind of errors:
You try to free with SysFreeString a memory which are allocated not with SysAllocString, but for example with CoTaskMemAlloc.
You have heap correct.
Heap corruptions are difficult to localize. The function HeapSetInformation can be very helpful. For example you can use
HeapSetInformation(NULL,HeapEnableTerminationOnCorruption,NULL,0);
Other good way is usage of HeapValidate function. For example you can define a function which verify all heaps pf the process (code in C, which can be easy rewritten in Delphi):
BOOL MyHeapValidate (void)
{
HANDLE hProcessHeaps[1024];
DWORD i;
DWORD dwNumberOfHeaps;
BOOL bSuccess = FALSE;
dwNumberOfHeaps = GetProcessHeaps (sizeof(hProcessHeaps)/sizeof(hProcessHeaps[0]),
hProcessHeaps);
if (dwNumberOfHeaps > sizeof(hProcessHeaps)/sizeof(hProcessHeaps[0])) {
MessageBox(NULL, TEXT("GetProcessHeaps()"),
TEXT("Error in MyHeapValidate()"), MB_OK);
return FALSE;
}
for (i=0; i<dwNumberOfHeaps; i++) {
bSuccess = HeapValidate (hProcessHeaps[i], 0, NULL);
if (!bSuccess)
return bSuccess;
}
return bSuccess;
}
The usage of this function can be like following:
void BadFunction(BSTR bstr)
{
LPOLESTR psz = OLESTR("Test12");
lstrcpy (bstr, psz);
}
int main()
{
LPOLESTR psz = OLESTR("Test");
BSTR bstr = SysAllocString (psz);
// verify that before call of BadFunction() all process heaps are OK!
if (!MyHeapValidate()) {
_tprintf(TEXT("heap is corrupted after the step 1.\n"));
return 1;
}
BadFunction(bstr);
if (!MyHeapValidate()) {
_tprintf(TEXT("heap is corrupted after the step 1.\n"));
return 1;
}
SysFreeString (bstr);
return 0;
}
With respect of inserting MyHeapValidate() in different suspected places you can very quickly local the place of corruption.
+1 for Larry Osterman's answer.
Some Windows memory functions behave slightly different under debugger: if they detect some kind of misuse - they trigger breakpoint to notify debugger. So, basically, your code is doing something wrong.
You can install hooks on SysAllocString/SysFreeString and redirect them to your memory manager (which should be in full debug mode) to collect more info. Or you can just pass these calls through to original functions, installing only a filter, which watches for memory actions.
And you can install debug symbols to get more info too (I'm not sure if Delphi debugger can use it, but Process Explorer - can. You can connect it to your process and see call stack).