I am having a problem in identifying a memory leak. I tried Instruments and it says that there is memory leak every time I call the function described below.
CFStringRef getStringFromLocalizedNIB(int cmdId)
{
IBNibRef nibRef;
WindowRef wind=NULL;
CFStringRef alertString;
CreateNibReference(CFSTR("main"), &nibRef);
CreateWindowFromNib(nibRef, CFSTR("Localized Strings"), &wind);
DisposeNibReference(nibRef);
ControlID alertID = {'strn',cmdId};
ControlRef alertRef;
GetControlByID(wind, &alertID,&alertRef);
GetControlData(alertRef, kControlNoPart, kControlStaticTextCFStringTag, sizeof(CFStringRef), &alertString, NULL);
return alertString;
}
Every time I call the function, I release the returned object.
CFStringRef lstr;
lstr = getStringFromLocalizedNIB(20);
//Use lstr;
CFRelease(lstr);
So can anybody please explain where the leak is?
If I understand correctly, you aren't showing the window created using CreateWindowFromNib(). I would expect the window to have the Carbon equivalent of release-on-close, and the CreateWindowFromNib() to be balanced by a ShowWindow(). I haven't done Carbon in 9 years though, so I'm not sure.
Try calling DisposeWindow() on wind to balance the create:
...
DisposeWindow(wind);
return alertString;
}
Related
According to The Create Rule I have created my own "constructor" - CFStringCreateFromGoString. It contains "Create" in its name. I expect that if I call CFStringCreateFromGoString then I own returned object.
But according to LLVM static analyzer this is not entirely true and in some cases I receive warning Incorrect decrement of the reference count of an object that is not owned at this point by the caller - see 1.h. And in other cases where is no warning - see 2.h.
From common.h:
CFStringRef CFStringCreateFromGoString(_GoString_ str) {
return CFStringCreateWithBytes(NULL, (UInt8*)_GoStringPtr(str), (CFIndex)_GoStringLen(str), kCFStringEncodingUTF8, false);
}
From 1.h:
CGRect _GetTextLineGeometry(CGContextRef context, _GoString_ str, CTFontRef font) {
CFStringRef _str = CFStringCreateFromGoString(str);
CGRect r = GetTextLineGeometry(context, _str, font); // no warning if I remove this line
CFRelease(_str); // warning here
return r;
}
From 2.h:
CTFontRef _CreateFontFromFile(_GoString_ path, struct FontSpec spec) {
CFStringRef _path = CFStringCreateFromGoString(path);
CTFontRef r = CreateFontFromFile(_path, spec);
CFRelease(_path); // no warning
return r;
}
Can somebody explain the difference between 1.h and 2.h?
Update 0
Thx matt for comment.
The problem was at GetTextLineGeometry - this function by mistake performed CFRelease(_str). Now I have no warnings.
But I don't understand why warning was in _GetTextLineGeometry instead of GetTextLineGeometry?
The name component "Create" does not perform any magic; it is just a matter of convention. So, for that matter, is the concept of "ownership".
So forget about all that and just think about the retain count.
The static analyzer, unlike mere human beings like you and me, can see all your code, and can count. It is counting the retains and releases on this object. When we get to CFRelease(_str) in your first example, you have previously released this same object, causing its retain count to drop to zero; so at this point you are performing an overrelease. Thus the static analyzer flags you at this point.
Now let's go back and think about it again from the point of view of "ownership". Only the "owner" of something can release it; that is what "ownership" means. But the static analyzer is perfectly willing to let you transfer ownership, if you know what you're doing. So if you want to "take ownership" by releasing in GetTextLineGeometry, that's fine with the static analyzer. But when when we get to CFRelease(_str), that is a second "owner" — and that isn't cricket. Thus, again, the static analyzer flags you here.
It is possible to cast a managed array<Byte>^ to some non-managed struct only using pin_ptr, AFAIK, like:
void Example(array<Byte>^ bfr) {
pin_ptr<Byte> ptr = &bfr[0];
auto data = reinterpret_cast<NonManagedStruct*>(ptr);
data->Header = 7;
data->Length = sizeof(data);
data->CRC = CalculateCRC(data);
}
However, is with interior_ptr in any way?
I'd rather work on managed data the low-level-way (using unions, struct-bit-fields, and so on), without pinning data - I could be holding this data for quite a long time and don't want to harass the GC.
Clarification:
I do not want to copy managed-data to native and back (so the Marshaling way is not an option here...)
You likely won't harass the GC with pin_ptr - it's pretty lightweight unlike GCHandle.
GCHandle::Alloc(someObject, GCHandleType::Pinned) will actually register the object as being pinned in the GC. This lets you pin an object for extended periods of time and across function calls, but the GC has to track that object.
On the other hand, pin_ptr gets translated to a pinned local in IL code. The GC isn't notified about it, but it will get to see that the object is pinned only during a collection. That is, it will notice it's pinned status when looking for object references on the stack.
If you really want to, you can access stack memory in the following way:
[StructLayout(LayoutKind::Explicit, Size = 256)]
public value struct ManagedStruct
{
};
struct NativeStruct
{
char data[256];
};
static void DoSomething()
{
ManagedStruct managed;
auto nativePtr = reinterpret_cast<NativeStruct*>(&managed);
nativePtr->data[42] = 42;
}
There's no pinning at all here, but this is only due to the fact that the managed struct is stored on the stack, and therefore is not relocatable in the first place.
It's a convoluted example, because you could just write:
static void DoSomething()
{
NativeStruct native;
native.data[42] = 42;
}
...and the compiler would perform a similar trick under the covers for you.
I found a strange problem while using Core Foundation Array! Here is the code snippet
fname = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s"), path, ep->d_name);
CFArrayAppendValue(fileNames, fname);
CFRelease(fname); <---- problem here
cnt = CFArrayGetCount(fileNames);
for (i = 0; i < cnt; i++) {
fname = CFArrayGetValueAtIndex(fileNames, i);
if (fname) {
ptr = (char *)CFStringGetCStringPtr(fname, CFStringGetFastestEncoding(fname));
The code crashes at the last line. Please correct me if I got this wrong. After I created the CFStringRef, I add it to CFArray. As per my understanding the object is now owned by CFArray. Hence I can safely remove the CFStringRef I originally allocated. But when I do CFRelease(fname); the code crashes when I access the array elements in the second part of the code. Can someone explain what is correct way of doing it? If I remove the CFRelease() then everything works fine.
As CFMutableArray Reference says:
The value parameter is retained by theArray using the retain callback
provided when theArray was created. If value is not of the type
expected by the retain callback, the behavior is undefined.
So looks like this is the issue of the fileNames array creation. Probably the third parameter of the CFArrayCreateMutable function. Since CFString is a CFType try to pass kCFTypeArrayCallBacks there.
There are a lot of samples for C#, but only some code snippets for C++ on MSDN. I have put it together and I think it will work, but I am not sure if I am releasing all the COM references I have to.
Your code is correct--the reference count on the IBufferByteAccess interface of *buffer is incremented by the call to QueryInterface, and you must call Release once to release that reference.
However, if you use ComPtr<T>, this becomes much simpler--with ComPtr<T>, you cannot call any of the three members of IUnknown (AddRef, Release, and QueryInterface); it prevents you from calling them. Instead, it encapsulates calls to these member functions in a way that makes it difficult to screw things up. Here's an example of how this would look:
// Get the buffer from the WriteableBitmap:
IBuffer^ buffer = bitmap->PixelBuffer;
// Convert from C++/CX to the ABI IInspectable*:
ComPtr<IInspectable> bufferInspectable(AsInspectable(buffer));
// Get the IBufferByteAccess interface:
ComPtr<IBufferByteAccess> bufferBytes;
ThrowIfFailed(bufferInspectable.As(&bufferBytes));
// Use it:
byte* pixels(nullptr);
ThrowIfFailed(bufferBytes->Buffer(&pixels));
The call to bufferInspectable.As(&bufferBytes) performs a safe QueryInterface: it computes the IID from the type of bufferBytes, performs the QueryInterface, and attaches the resulting pointer to bufferBytes. When bufferBytes goes out of scope, it will automatically call Release. The code has the same effect as yours, but without the error-prone explicit resource management.
The example uses the following two utilities, which help to keep the code clean:
auto AsInspectable(Object^ const object) -> Microsoft::WRL::ComPtr<IInspectable>
{
return reinterpret_cast<IInspectable*>(object);
}
auto ThrowIfFailed(HRESULT const hr) -> void
{
if (FAILED(hr))
throw Platform::Exception::CreateException(hr);
}
Observant readers will notice that because this code uses a ComPtr for the IInspectable* we get from buffer, this code actually performs an additional AddRef/Release compared to the original code. I would argue that the chance of this impacting performance is minimal, and it's best to start from code that is easy to verify as correct, then optimize for performance once the hot spots are understood.
This is what I tried so far:
// Get the buffer from the WriteableBitmap
IBuffer^ buffer = bitmap->PixelBuffer;
// Get access to the base COM interface of the buffer (IUnknown)
IUnknown* pUnk = reinterpret_cast<IUnknown*>(buffer);
// Use IUnknown to get the IBufferByteAccess interface of the buffer to get access to the bytes
// This requires #include <Robuffer.h>
IBufferByteAccess* pBufferByteAccess = nullptr;
HRESULT hr = pUnk->QueryInterface(IID_PPV_ARGS(&pBufferByteAccess));
if (FAILED(hr))
{
throw Platform::Exception::CreateException(hr);
}
// Get the pointer to the bytes of the buffer
byte *pixels = nullptr;
pBufferByteAccess->Buffer(&pixels);
// *** Do the work on the bytes here ***
// Release reference to IBufferByteAccess created by QueryInterface.
// Perhaps this might be done before doing more work with the pixels buffer,
// but it's possible that without it - the buffer might get released or moved
// by the time you are done using it.
pBufferByteAccess->Release();
When using C++/WinRT (instead of C++/CX) there's a more convenient (and more dangerous) alternative. The language projection generates a data() helper function on the IBuffer interface that returns a uint8_t* into the memory buffer.
Assuming that bitmap is of type WriteableBitmap the code can be trimmed down to this:
uint8_t* pixels{ bitmap.PixelBuffer().data() };
// *** Do the work on the bytes here ***
// No cleanup required; it has already been dealt with inside data()'s implementation
In the code pixels is a raw pointer into data controlled by the bitmap instance. As such it is only valid as long as bitmap is alive, but there is nothing in the code that helps the compiler (or a reader) track that dependency.
For reference, there's an example in the WriteableBitmap::PixelBuffer documentation illustrating the use of the (otherwise undocumented) helper function data().
In Cocoa on the Mac, I'd like to detect when a window belonging to another app is moved, resized, or repainted. How can I do this?
You would need to use the Accessibility APIs, which are plain-C, located inside the ApplicationServices framework. For instance:
First you create an application object:
AXUIElementRef app = AXUIElementCreateApplication( targetApplicationProcessID );
Then you get the window from this. You can request the window list and enumerate, or you can get the frontmost window (look in AXAttributeConstants.h for all the attribute names you'd use).
AXUIElementRef frontWindow = NULL;
AXError err = AXUIElementCopyAttributeValue( app, kAXMainWindowAttribute, &frontWindow );
if ( err != kAXErrorSuccess )
// it failed -- maybe no main window (yet)
Now you can request notification via a C callback function when a property of this window changes. This is a four-step process:
First you need a callback function to receive the notifications:
void MyAXObserverCallback( AXObserverRef observer, AXUIElementRef element,
CFStringRef notificationName, void * contextData )
{
// handle the notification appropriately
// when using ObjC, your contextData might be an object, therefore you can do:
SomeObject * obj = (SomeObject *) contextData;
// now do something with obj
}
Next you need an AXObserverRef, which manages the callback routine. This requires the same process ID you used to create the 'app' element above:
AXObserverRef observer = NULL;
AXError err = AXObserverCreate( applicationProcessID, MyObserverCallback, &observer );
if ( err != kAXErrorSuccess )
// handle the error
Having got your observer, the next step is to request notification of certain things. See AXNotificationConstants.h for the full list, but for window changes you'll probably only need these two:
AXObserverAddNotification( observer, frontWindow, kAXMovedNotification, self );
AXObserverAddNotification( observer, frontWindow, kAXResizedNotification, self );
Note that the last parameter there is passing an assumed 'self' object as the contextData. This is not retained, so it's important to call AXObserverRemoveNotification when this object goes away.
Having got your observer and added notification requests, you now want to attach the observer to your runloop so you can be sent these notifications in an asynchronous manner (or indeed at all):
CFRunLoopAddSource( [[NSRunLoop currentRunLoop] getCFRunLoop],
AXObserverGetRunLoopSource(observer),
kCFRunLoopDefaultMode );
AXUIElementRefs are CoreFoundation-style objects, so you need to use CFRelease() to dispose of them cleanly. For cleanliness here, for example, you would use CFRelease(app) once you've obtained the frontWindow element, since you'll no longer need the app.
A note about Garbage-Collection: To keep an AXUIElementRef as a member variable, declare it like so:
__strong AXUIElementRef frontWindow;
This instructs the garbage collector to keep track of this reference to it. When assigning it, for compatibility with GC and non-GC, use this:
frontWindow = (AXUIElementRef) CFMakeCollectable( CFRetain(theElement) );
Further research turned up "Quartz Display Services"
The interesting function for my needs is CGRegisterScreenRefreshCallback.