Dynamically created TFrame causes Windows user object leak - c++builder

In a C++ Builder 6 test project, I try to understand the relation between the TWinControl classes of the VCL and Windows user objects, because I'm hunting a leak of user objects in my original application where I use some levels of nested frames, created periodically at runtime, that causes my application to crash after some days.
In the test project I observe a strange behaviour. When I add a dynamically created TFrame object to a panel, the count of user objects increases by 2. If I remove a frame by deletion, the user object count is decreased by 1. If I add it again, the increment is 1. If I add more than 1 frame, the increment is 2 after exceeding the last maximum value of frames. This is the code to reproduce this:
MainForm.cpp
#include <vcl.h>
#pragma hdrstop
#include "MainFrm.h"
#pragma resource "*.dfm"
TMainForm *MainForm;
int UserObjectCount() {
return GetGuiResources(GetCurrentProcess(), 1);
}
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
}
void __fastcall TMainForm::AddButtonClick(TObject *Sender)
{
String msg = "add: "+IntToStr(UserObjectCount())+",";
(new TFrame(static_cast<TComponent*>(NULL)))->Parent = FramesPanel;
trace(msg+IntToStr(UserObjectCount()));
}
void __fastcall TMainForm::RemoveButtonClick(TObject *Sender)
{
if (!FramesPanel->ControlCount) return;
String msg = "rem: "+IntToStr(UserObjectCount())+",";
FramesPanel->Controls[0]->Free();
trace(msg+IntToStr(UserObjectCount()));
}
void TMainForm::trace(const String& msg)
{
TraceMemo->Lines->Add(msg);
}
It looks like a kind of caching. See the (grouped) excerpt of the trace (format action: before,after):
add: 28,30
rem: 30,29
add: 29,30
add: 30,32
rem: 32,31
rem: 31,30
add: 30,31
add: 31,32
add: 32,34
rem: 34,33
rem: 33,32
rem: 32,31
Another observation: If I use TPanel instead of TFrame, the behaviour is is trivial.
As to understand whether this is a Windows feature, I built another test application with Lazarus (Google didn't help). Here the user object count behaviour is unsurprising: increment and decrement compensate each other.
What is the explanation of this caching-like behaviour? How to get back to the initial count of user objects?
I'm sorry for pushing you back into the old times of BCB6.

Related

How does Vala handle reference counting with multithreading?

As far as I understand, in multithreaded environment reference counting should be performed with locking to ensure all threads see the same snapshot of memory. But locking slows down perfomance. How does Vala solve this problem?
Reference counting is mostly handled in GObject (for GLib.Object-derived types), which in turn uses the Atomic Operations in GLib. Atomics are a tricky subject; if you want to get into details a good place to start is Herb Sutter's Atomic Weapons talk from a few years ago. I would recommend watching the videos even if you're never going to put them to use (and 99.9% of programmers should never put them to use) because it will give you a much better understanding of how computers really work.
The name "atomics" can be a bit misleading; it's not really about atomicicity, though that's part of it. The operations are atomic in the sense that the change is either made in its entirety or not at all, which is vital, but the more interesting part is that atomics act as barriers which prevent the compiler from re-ordering operations across the barrier. Herb Sutter's talk goes into a lot of detail about this which I'm not going to repeat here.
For example, think about a simple unprotected reference counter:
typedef struct {
int reference_count = 0;
} Foo;
Foo* foo_create(void) {
Foo* foo = malloc(sizeof(Foo));
foo->reference_count = 1;
}
void ref(Foo* foo) {
++(foo->reference_count);
}
void unref(Foo* foo) {
if (--(foo->reference_count) == 0) {
free(foo);
}
}
I'm going to assume you can see the problems with leaving this unprotected because I'm writing a SO post not a book.
The specific atomic operation we're interested in is compare-and-swap (CAS), which basically provides the ability to perform this operation safely:
bool cas(int* value, int* expected, int desired) {
if (*value == *expected) {
*value = desired;
return true;
} else {
return false;
}
}
Using this, we would change our refcounting implementation above to something like:
typedef struct {
int reference_count = 0;
} Foo;
Foo* foo_create(void) {
Foo* foo = malloc(sizeof(Foo));
/* No atomics needed, we haven't made the value public yet */
foo->reference_count = 1;
}
void ref(Foo* foo) {
int old_refcount;
int new_refcount;
do {
current_refcount = foo->reference_count;
new_refcount = current_refcount + 1;
} while (!cas (&(foo->reference_count), &old_refcount, new_refcount))
}
void unref(Foo* foo) {
int old_refcount;
int new_refcount;
do {
current_refcount = foo->reference_count;
new_refcount = current_refcount - 1;
} while (!cas (&(foo->reference_count), &old_refcount, new_refcount));
if (new_refcount == 0) {
free(foo);
} else if (new_recount < 0) {
// Double-free bug, code should not be reached!
}
}
But locking slows down perfomance.
So do atomics. A lot. But also a lot less than a higher-level lock would. For one thing, if you were working with a mutex what you are doing would basically be:
Acquire the lock.
Perform the operation.
Release the lock.
With atomics, we're basically begging forgiveness instead of asking permission:
Attempt to perform the operation.
Then we just look to see whether the operation was successful (i.e., if cas() returned true).
The operation is also a lot smaller and faster; with a mutext, you would probably acquire the lock then read the current value, increment / decrement it, then release the lock. With atomics, the CAS operation gets wrapped up in a single CPU instruction.
The CPU still has to deal with cache coherency by making sure that next time any other core (a bit oversimplified since even within a core there are multiple caches) asks to read the data they are presented with the new data. In other words, atomic reference counting is bad for performance, but it's a lot less bad than a mutex. Frankly, if you want reference counting instead of tracing garbage collection atomics are pretty much your least-bad option.

C++: How do I make a VCL component reference itself?

I'm using C++ Builder in RAD Studio 10.2. I'm not sure if I asked this correctly in the title, but what I'm trying to say is that whenever I use the C++ keyword 'this', it references the Parent of the component that I'm trying to access, but not the component itself.
For example, the code below changes the Form's color and font color instead of the Panel's color and font color:
void __fastcall TForm1::Panel1MouseEnter(TObject *Sender)
{
this->Color = cl3DLight;
this->Font->Color = clMaroon;
}
Also, if I do the same as above but omit the keyword 'this', it still changes the Form's properties instead of the Panel's (see code below).
void __fastcall TForm1::Panel1MouseEnter(TObject *Sender)
{
Color = cl3DLight;
Font->Color = clMaroon;
}
How would I code this so it accesses the Panel's 'Color' and 'Font->Color' instead of the Form's? Thank you.
Note: The reason that I haven't just done it as: Panel1->Color = "cl3DLight"; is because I'm trying to find a way to do it for components created at run-time.
The Sender parameter represents the component that is generating the event. You can typecast that pointer to the proper type in order to access that component's properties.
If you know for sure that everything attached to the event is a TPanel, you can typecast it directly (as Remy pointed out in comments below):
void __fastcall TForm1::Panel1MouseEnter(TObject *Sender)
{
TPanel *panel = static_cast<TPanel *>(Sender);
panel->Color = cl3DLight;
panel->Font->Color = clMaroon;
}
If you're using the same event handler for different control types, you can test for the appropriate type instead:
void __fastcall TForm1::Panel1MouseEnter(TObject *Sender)
{
TPanel *panel = dynamic_cast<TPanel *>(Sender);
if (panel)
{
panel->Color = cl3DLight;
panel->Font->Color = clMaroon;
}
}

Better way to detect WiFi enabled/disabled on iOS?

After an unbelievable amount of teeth gnashing, I finally have a method that successfully detects if WiFi is enabled on iOS independent of whether it's connected or not. There are at least a couple uses for such a thing, and I don't think this violates the spirit or the letter of Apple Law(tm).
However, it's ugly and probably won't work forever. It currently works on iOS 10.2.1, as of Jan 31, 2017. I'll put my answer below and hope that someone can improve it. I've heavily researched Reachability (doesn't meet the requirements), CaptiveNetwork, HotspotHelper, SCNetworkConfiguration, Xamarin's System.Net.NetworkInterface, and more. This is it that actually works as far as I can tell.
The gist of the solution is that when there's TWO interfaces reported by getifaddrs() with the name "awdl0" then WiFi is enabled. Just one and it's disabled.
I credit pebble8888 for pointing me to https://github.com/alirp88/SMTWiFiStatus which is Objective-C, where the lack of comments make it hard to understand what's going on or what the author's intention was.
Here's my full and complete Xamarin/C# solution, which ought to be pretty readable for any other major language user:
using System;
using System.Runtime.InteropServices;
namespace Beacon.iOS
{
/// <summary>
/// code stolen from the Xamarin source code to work around goofy interactions between
/// the good-god-why-would-it-work-that-way iOS and the entirely reasonable Xamarin
/// (it doesn't report interfaces that are reported multiple times)
/// </summary>
class XamHack
{
//
// Types
//
internal struct ifaddrs
{
#pragma warning disable 0649
public IntPtr ifa_next;
public string ifa_name;
public uint ifa_flags;
public IntPtr ifa_addr;
public IntPtr ifa_netmask;
public IntPtr ifa_dstaddr;
public IntPtr ifa_data;
#pragma warning restore
}
//
// OS methods
//
[DllImport("libc")]
protected static extern int getifaddrs(out IntPtr ifap);
[DllImport("libc")]
protected static extern void freeifaddrs(IntPtr ifap);
//
// Methods
//
/// <summary>
/// Our glorious hack. I apologize to the programming gods for my sins
/// but this works (for now) and functionality trumps elegance. Even this.
/// Reverse engineered from: https://github.com/alirp88/SMTWiFiStatus
/// </summary>
public static bool IsWifiEnabled()
{
int count = 0;
IntPtr ifap;
// get the OS to put info about all the NICs into a linked list of buffers
if (getifaddrs(out ifap) != 0)
throw new SystemException("getifaddrs() failed");
try
{
// iterate throug those buffers
IntPtr next = ifap;
while (next != IntPtr.Zero)
{
// marshall the data into our struct
ifaddrs addr = (ifaddrs)Marshal.PtrToStructure(next, typeof(ifaddrs));
// count the instances of the sacred interface name
if ("awdl0" == addr.ifa_name)
count++;
// move on to the next interface
next = addr.ifa_next;
}
}
finally
{
// leaking memory is for jerks
freeifaddrs(ifap);
}
// if there's two of the sacred interface, that means WiFi is enabled. Seriously.
return (2 == count);
}
} // class
} // namespace

Debugging trivial functions in Objective-C

Recently I just started working on iOS game programming, and I find several things confusing. (FYI, I am working on a simple game with code provided on makegamewith.us)
First, I just found out that only the main function is executed. By this I mean we use the main function to activate iOS simulator, so that we will be able to load our game. Then I realize that breakpoints only work in main functions. As I put breakpoints in other files (such as creature.m, a game component), despite that I use a function to create creature objects in the game, Xcode won't stop at that function. The iOS simulator will be called, and then the game will be automatically loaded.
So here is the question: how can I debug then?
I assume that function is called when I run the game, but Xcode just ignores any other function in other files except the main function in main.m.
Also, I encountered several "Couldn't find member variable" situations. I wonder how to prevent this from happening. The whole sprite builder publishing to Xcode thing appears blurry. I would appreciate if someone can explain how the whole thing works.
Update:
I realize that I didn't explicitly call any of the functions I have in other files (for instance, Grid.m as shown below). By main function, I mean the int main function in main.m. So the problem might possibly be that I didn't explicitly call that function in main? (but I think what main.m is responsible for is launching the program.)
In main.m:
int main(int argc, char *argv[]) {
#autoreleasepool //if I put a breakpoint here this will definitely work
{
int retVal = UIApplicationMain(argc, argv, nil, #"AppController");
return retVal;
}
}
Grid.m
#import "Grid.h"
#import "Creature.h"
// these are variables that cannot be changed
static const int GRID_ROWS = 8;
static const int GRID_COLUMNS = 10;
#implementation Grid {
NSMutableArray *_gridArray;
float _cellWidth;
float _cellHeight;
}
- (void)onEnter
{
[super onEnter];
[self setupGrid];
// accept touches on the grid
self.userInteractionEnabled = YES;
}
- (void)setupGrid //****if I put breakpoint here, it doesn't work****
{
// divide the grid's size by the number of columns/rows to figure out the right width and height of each cell
_cellWidth = self.contentSize.width / GRID_COLUMNS;
_cellHeight = self.contentSize.height / GRID_ROWS;
float x = 0;
float y = 0;
// initialize the array as a blank NSMutableArray
_gridArray = [NSMutableArray array];
// initialize Creatures
for (int i = 0; i < GRID_ROWS; i++) {
// this is how you create two dimensional arrays in Objective-C. You put arrays into arrays.
_gridArray[i] = [NSMutableArray array];
x = 0;
for (int j = 0; j < GRID_COLUMNS; j++) {
Creature *creature = [[Creature alloc] initCreature];
creature.anchorPoint = ccp(0, 0);
creature.position = ccp(x, y);
[self addChild:creature];
// this is shorthand to access an array inside an array
_gridArray[i][j] = creature;
// make creatures visible to test this method, remove this once we know we have filled the grid properly
creature.isAlive = YES;
x+=_cellWidth;
}
y += _cellHeight;
}
}
#end
Take a look at your main() function -- almost the only thing it does is to call UIApplicationMain(). This is true for any iOS application. So the real work is being done by UIApplicationMain(), and we should find out about that. Here's the description from the docs:
This function instantiates the application object from the principal
class and instantiates the delegate (if any) from the given class and
sets the delegate for the application. It also sets up the main event
loop, including the application’s run loop, and begins processing
events. If the application’s Info.plist file specifies a main nib file
to be loaded, by including the NSMainNibFile key and a valid nib file
name for the value, this function loads that nib file.
So if there's a problem with your app, it's likely related to the application delegate, your AppController class. Set a breakpoint in your -[AppController application:willFinishLaunchingWithOptions:] method -- that's what the application itself will call on its delegate when the app is ready to run. Your UIApplicationMain() call in main() looks OK, so the debugger should hit a breakpoint in your ...didFinishLaunching... method. Step through that method and make sure that you're setting up a window, setting a root view controller, etc. If you're not sure what needs to happen, try creating a new single-view project and looking at the code that's provided there.

Dereference pointer with ARC in C function in iOS

I'm using The Amazing Audio Engine to handle playback in syncing in an iOS app.
The framework requires you to use C functions as the call back (playbackTimingReceiver) which is called on the audio thread. You then need to message the main thread again using a C function (AEAudioControllerSendAsynchronousMessageToMainThread) to which you pass a handler (pageTurnHandler).
I'm not overly experienced working with C but as I understand it I'm passing a pointer in the message which needs to be dereferenced.
Which I can achieve successfully with the line:
PlaybackManager* receiver = *((PlaybackManager**)userInfo);
But only if I turn ARC off in the project for that file using the -fno-objc-arc flag in compiled sources on the projects target.
To my question, is it possible to achieve this with ARC turned on? If so what is the correct syntax?
Relevant code segment:
#pragma mark - Audio Timing Callback
-(AEAudioControllerTimingCallback)timingReceiverCallback
{
return playbackTimingReceiver;
}
static void playbackTimingReceiver(PlaybackManager* receiver,
AEAudioController *audioController,
const AudioTimeStamp *time,
UInt32 const frames,
AEAudioTimingContext context)
{
receiver->_hostTime = getUptimeInMilliseconds(time->mHostTime);
AEAudioControllerSendAsynchronousMessageToMainThread(audioController,
pageTurnHandler,
&audioController,
sizeof(id));
}
static void pageTurnHandler(AEAudioController *audioController, void *userInfo, int userInfoLength)
{
PlaybackManager* receiver = *((PlaybackManager**)userInfo);
NSLog(#"Receiver:%#", receiver);
}
PlaybackManager * receiver = (__bridge_transfer id)*(void **)userInfo;
should do the trick. This first casts the userInfo to a pointer-to-pointer, because it contains the address of the original object pointer. Dereference that to get the original pointer, and use __bridge_transfer with a type -- id or PlaybackManager will work -- to tell ARC that the dereferenced value is actually an object that it needs to take care of.
Without running the code there appear to be two errors:
1) You are passing the contents of audioController when it looks like you meant to pass the contents of receiver - so last two args to AEAudioControllerSendAsynchronousMessageToMainThread should be &receiver & sizeof(PlaykbackManager *)
2) You need a bridge cast to get the object reference back out
Something like:
static void playbackTimingReceiver(PlaybackManager* receiver,
AEAudioController *audioController,
const AudioTimeStamp *time,
UInt32 const frames,
AEAudioTimingContext context)
{
receiver->_hostTime = getUptimeInMilliseconds(time->mHostTime);
AEAudioControllerSendAsynchronousMessageToMainThread(audioController,
pageTurnHandler,
&receiver,
sizeof(PlaybackManager*));
}
static void pageTurnHandler(AEAudioController *audioController, void *userInfo, int userInfoLength)
{
PlaybackManager* receiver = (__bridge Playback *)*((PlaybackManager**)userInfo);
NSLog(#"Receiver:%#", receiver);
}
Note: when passing object references from the ARC controlled world to the C world you often transfer ownership on the way in - so ARC doesn't release the referenced object - and transfer ownership back on the way back out - so ARC resumes ownership management. However due to the nature of AEAudioControllerSendAsynchronousMessageToMainThread, where userInfo is passed by address and copied internally - hence the size argument, it is tricker to transfer ownership. Therefore the above code does not. This means you must make sure that whatever object receiver references stays alive by having another owner.
You can just tell ARC the type of storage you would like:
PlaybackManager *audioBufferPlayer = *(__weak PlaybackManager **)userInfo;
Just be sure to do necessary nil checks before accessing any properties or calling any methods.

Resources