Hey, I am making some stuff in Objective-C++... And I must say that I am a total newbie when it comes to the Objective-C part... I don't really want to learn it, I kinda just need it for accessing a few Mac APIs (ObjC is such a dumb language).
So - compiling with g++ -x objective-c++ - and I somehow keep getting this warning:
XXX may not respond to YYY
First it was with a NSScreen, now it is with a NSWindow:
NSWindow may not respond to +initWithContentRect:styleMask:backing:defer:
I saw somewhere that I should cast it to id, but didn't work, throwing absolutely cryptic errors...
So - WHAT does this warning actually mean and HOW am I supposed to make it stop?
EDIT: Okay, apparently I need to ALLOCATE an instance first, then I can call its init function... Anyways, now the GCC is reporting:
confused by earlier errors, bailing out
And NOTHING else. This is the ONLY error that it reports. I figured that there is some error in my code that doesn't get reported... So I will post the whole file where the problem is here:
ONXeWindow::ONXeWindow(int px, int py, int sw, int sh, bool resizable){
NSRect wr = NSMakeRect(px, py, sw, sh);
int wf = 1; // titled
wf += 2; // closable
wf += 4; // miniaturizable
wf += (resizable ? 8 : 0); // resizable
wf += (false ? 128 : 0); // metal bg
useWindow = [[NSWindow alloc] initWithContentRect:wr styleMask:wf backing:2 defer:YES];
}
Also, YES, framework AppKit was imported (in the header file) - I am not going to confuse you with my weird file scheme here.
The message isn't really cryptic, you just don't know the language (and don't care to, by your own admission).
Since Objective-C methods are dispatched dynamically at run-time, you can call a method that the compiler doesn't have any knowledge of, however, the compiler is warning you that you're doing so. The + in the beginning of the method name means that you're calling a class method (a - would indicate that you're calling a method on an instance). Since NSWindow has no class method named initWithContentRect:styleMask:backing:defer:, the compiler is giving you a warning, and in this case, it's a pretty good one.
You probably wrote something like:
NSWindow* myWindow = [NSWindow initWithContentRect:rect styleMask:0 backing:0 defer:NO];
when you meant to write something like:
NSWindow* myWindow = [[NSWindow alloc] initWithContentRect:rect styleMask:0 backing:0 defer:NO];
The first one sends the message directly to the class, but this is an instance method. You need to allocate an instance of NSWindow first, then send the init message. Also, clang tends to give much better warning and error messages than gcc. Clang 2.0 also handles C++ and ObjC++ pretty well, so it might be worth it to switch to clang.
Checkout this example, looks like you are not allocating your objects.
Related
So, if I want to write an Xll and license the code then I need a point at which to check the license file and if license is invalid then I want the Xll to stop working.
I see xlAutoOpen looks like a good place to inspect the license file. I also see that xlAutoOpen must return 1 according to the documentation, what happens if something other than 1 is returned? Can I abort the Xll opening? Can I force an unload?
Are there any better places to check the license and refuse to operate. Surely, I don't have to wait until the first worksheet function invocation.
I am unfamiliar with this framework currently so forgive newbie-ness.
EDIT: I suppose I can refuse to call xlfRegister. That will prevent operation.
EDIT2: From the Excel SDK Help file
xlAutoAdd ... can be used to ... check licensing information, for example.
Also, found that on MSDN xlAutoAdd
You should check licensing information in xlAutoOpen since this function is the first entry point to activate the XLL and is always called by Excel. If password is invalid just returns 0 to indicates failure to excel and do not register your UDFs (quit before to call xlfRegister).
I have noticed that if you register your UDFs and that you returns 0 ,
the xll is still loaded and UDFs are available, so the return
variable from xlAutoOpen does not seem to be taken into account by
Excel but by convention I believe it is better to keep returning zero
to indicate failure.
I believe MSDN doc is misleading.
xlAutoAdd is not suitable to check license since it is an optional function that is called only when the XLL is added by the Add-In Manager or when it is opened as a document (using File/Open). I assume that you may have trial licence and so that you should check it at every load time if the user's licence is still valid.
Example
Usually, you call xlAutoOpen from xlAutoAdd so your check will still be done :
pseudo code :
int __stdcall xlAutoAdd(void)
{
if(!Isinitialised)
if( xlAutoOpen() == 0) // licence check is still performed
returns 0 ;
...
MessageBoxA(GetActiveWindow(), "Thank you to install ...", "AutoOpen", MB_OK);
Isinitialised = true;
}
since xlAutoOpen is always called by Excel you should perform a similar check inside it :
bool Isinitialised = false;
int __stdcall xlAutoOpen(void) // Register the functions
{
if(Isinitialised)
return 1;
if(!ValidLicense()) // check licence in xlAutoOpen
return 0;
// continue initialization , registration ..
.....
Isinitialised = true;
}
Finally note that you can omit xlAutoAdd because it has no adverse consequences and is not required by Excel. Personally I do not use this function.
I tried to iterate over a basic blocks in a specific routine, but i found some problems:
VOID Routine(RTN rtn, VOID *v)
{
RTN_Open(rtn)
for (BBL bbl = RTN_BblHead(rtn); BBL_Valid(bbl); bbl = BBL_Next(bbl))
{ /* some code */ }
RTN_Close(rtn);
}
error: deprecated-declarations,
How can i fix that error, or do it by another way ?
You have a deprecated-declarations warning because RTN_BblHead is now deprecated. Use RTN_InsHead instead.
From include\pin\gen\image.ph:
/* DO NOT EDIT */
/* RTN_BblHead is now deprecated. See RTN_InsHead.
*/
extern PIN_DEPRECATED_API BBL RTN_BblHead(RTN x);
This is also mentioned in the documentation: RTN_BblHead
You can also pass -Wno-deprecated-declarations to GCC to suppress this warning.
Edit
Remember that PIN is above all a DBI (dynamic binary instrumentation) framework: it is extremely good when it comes to instrument the executed code flow, and less good when it needs to break down non executed code.
Routine instrumentation lets the Pintool inspect and instrument an entire routine when the image it is contained in is first loaded' but as the documentation points:
A Pintool can walk the instructions of a routine. There is not enough
information available to break the instructions into BBLs.
Pin find the instructions of a RTN through static discovery, so Pin cannot guarantee that it will find all the instructions in the RTN and this is even more difficult for BBLs. My guess is that they tried at some point (hence the availability of RTN_BblHead in the past) to provide static discovery of BBLs but the discovery rate was too low (or too error prone) to be deemed acceptable, so the function became deprecated.
In short, yes you need to discover a RTN instructions by instructions (knowing that pin might miss some instructions as this is done statically). You can only discover the BBLs of a routine if the routine is executed at some point.
I saw a very strange behavior in my rebus handler which is self hosted in exe. Right after sending response using bus.send method it adds up some memory consumed by process. I tried to look up object graph using memory profile and found that rebus is holding response message in serialized format somewhere.
Object graph was showing below hierarchy to the root.
System.Message --> CachedBodyMessage --> stream
Give me some pointers if anybody is aware of this thing.
I understand that a memory leak is a grave concern, but my belief is that it is unlikely that Rebus should contain a memory leak.
This belief is rooted in the fact that I have been running Windows Service-hosted Rebus endpoints in production for 1,5 years now, and several of them (e.g. the timeout managers) have sometimes been running for several months without being restarted.
I'd like to be absolutely bulletproof sure though, so I'm willing to investigate the issue you're reporting.
You're mentioning "CachedBodyMessage" - judging by the names of fields inside System.Messaging.Message, it sounds like it's something within MSMQ. To try to reproduce your issue, I coded the following test:
[Test, Ignore("Only works in RELEASE mode because otherwise object references are held on to for the duration of the method")]
public void DoesNotLeakMessages()
{
// arrange
const string inputQueueName = "test.leak.input";
var queue = new MsmqMessageQueue(inputQueueName);
disposables.Add(queue);
var body = Encoding.UTF8.GetBytes(new string('*', 32768));
var message = new TransportMessageToSend
{
Headers = new Dictionary<string, object> { { Headers.MessageId, "msg-1" } },
Body = body
};
var weakMessageRef = new WeakReference(message);
var weakBodyRef = new WeakReference(body);
// act
queue.Send(inputQueueName, message, new NoTransaction());
message = null;
body = null;
GC.Collect();
GC.WaitForPendingFinalizers();
// assert
Assert.That(weakMessageRef.IsAlive, Is.False, "Expected the message to have been collected");
Assert.That(weakBodyRef.IsAlive, Is.False, "Expected the body bytes to have been collected");
}
which verifies that the sent transport message is collected as it should (will only do this in RELEASE mode though, because of the way DEBUG mode holds on to object references within scope)
I'll try and run the TimePrinter sample now and leave it running for a while to see if I can reproduce the issue. If you stumble upon more information about e.g. exactly which objects are leaking, it would be very helpful.
Thanks again for taking the time to report your worries to me :)
Followup:
I've modified the TimePrinter sample so that it sends 50 msg/s and includes a 64 KB random string payload with each message, and I've tracked the memory usage for almost four hours now. As you can see, it does not look like memory is being leaked.
I'll leave it running the rest of the day, just to be sure.
Maybe you can tell me some more about why you suspected there was a memory leak in the first place?
Update:
As you can see from the trace, it has now been running for 7 hours and thus more than 1,200,000 messages containing more than 70 GB of data has been sent and consumed by the same process. If cached message bodies were leaking, I am pretty sure that we would have been able to see something rising on the graph.
We have a lot of code written that makes use of the standard template library. I would like to integrate some of our apps into the windows shell, which should provide a better experience for our users.
One piece of integration involves a Shell Preview provider, the code is very straight forward, however, I’m stuck on the best way to implement something.
The shell is giving me, via my preview handler, an IStream object and I need to convert/adapt it to an std::ifstream object, primarily so that std::getline can get called further down the callstack.
I was wondering if there was a “standard” way of doing the adapting or do I need to role up my sleeves and code?
TIA.
Faffed around with this for a while:
std::stringstream buff;
BYTE ib[2048];
ULONG totread=0, read=0, sbuff = 2048;
HRESULT hr;
do {
hr = WinInputStream->Read(ib, sbuff, &read);
buff.write(ib, read);
totread+=read;
} while((sbuff == read) && SUCCEEDED(hr));
if(totread == 0) return false;
ifstream i;
TCHAR* ncbuff = const_cast<TCHAR*>(buff.str().c_str());
i.rdbuf()->pubsetbuf(ncbuff, buff.str().length());
But didn't like having to read it all into memory, for it to be processed again.
So I implemented my preview handler using IInitializeWithFile instead.
So, I'm using the HTTPConnection Class, like so:
HttpConnection c =
(HttpConnection)Connector.open("http://147.117.66.165:8000/eggs.3gp");
Following what LOOKS like the right way to do things in the Blackberry JDE API.
However, my code crashes if I try to do just about anything with the variable 'c'.
.getType()
.getInputStream()
.getStatus()
all cause it to crash.
I can, however get the URL from it, and I can look at the variable 'c' itself to know that it did, in fact, get created.
Did I manage to create a broken Connection? Do I need to do something else to actually do things with the connection? Under what circumanstances will this happen (I know the link is good, I can use the blackberry's browser to visit it).
Am I just using HttpConnection wrong? How would I do things correctly?
What error is it throwing when it crashes? You may want to try adding the "Connector.READ_WRITE" as a second argument to your open call - even if it's just a "read only" connection like a GET, some OSes such as 4.6 will throw an exception unless you open it in read/write mode.
I figured out what was wrong by finding some sample code that was using HttpConnection, (at least, I think I did, at least, I can access all those variables, now). Before, I wasn't ever casting it as a "Stream Connection" (the examples I saw had it cast from Connector to HTTPConnection).
StreamConnection s = null;
s = (StreamConnection)Connector.open("http://10.252.9.15/eggs.3gp");
HttpConnection c = (HttpConnection)s;
InputStream i = c.openInputStream();
System.out.println("~~~~~I have a connection?~~~~~~" + c);
System.out.println("~~~~~I have a URL?~~~~" + c.getURL());
System.out.println("~~~~~I have a type?~~~~" + c.getType());
System.out.println("~~~~~I have a status?~~~~~~" + c.getResponseCode());
System.out.println("~~~~~I have a stream?~~~~~~" + i);
player = Manager.createPlayer(i, c.getType());
Even though the stream is now successfully being created, I'm still having problems USING it, but that might be because my connection is so slow.
The API documentation for HttpConnection suggests the first call should be to c.getResponseCode(), try that.
You should find everything you need in my blog post "An HttpRequest and HttpResponse library for BB OS5+"
And for invoking media within your application you can do either a browser invokation or directly from app. You would probably be best to use the browser like so:
BrowserSession invokeHighQuality = Browser.getDefaultSession();
invokeHighQuality.displayPage("URL goes here");
OR you can try this:
// CHAPI invocation
Invocation invoke = new Invocation(_data.getUrl(), null, BlackBerryContentHandler.ID_MEDIA_CONTENT_HANDLER, false,
null);
try {
Registry.getRegistry(YourAppClass.class.getName()).invoke(invoke);
} catch (Throwable t) {
}