ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Okay, so I'm building a couple of C++ source files with '-Wall -ansi -pendantic', and I'm only getting a single warning (I plan to use this code as a demonstration/make-me-look-good-for-interviews, so I really want it to be perfect).
The warning I get is that "ANSI C++ forbids casting between pointer-to-object and pointer-to-function". I am casting from a an object- to function-pointer intentionally. The referenced line is pulling a symbol from a dynamically loaded module via dylsym() and casting it to the appropriate function type.
My question is, is there some correct way to make this error go away? I'd prefer not to use funky #pragma's or other non-portability if I can. Is there some "correct" way to do this cast? Or will I just have to live with the one warning?
Note that the typedef was moved into the segment to present just one clip, it originally appeared at the top of the file. "ids[name].second" refers to a Glib::Module, a wrapper around dlopen/dlsym/dlclose. It's putting the symbol into its second argument.
I had thought that anything went if you passed through a void*. Is this then a gcc bug that I should report?
What type is applets? It looks like you have two conjoined statements as the argument for push_back: ((applet_creator)ptr) doesn't contain a dereference operator, so it has no formal relationship with (*(new Configuration(*backings[id].first, id))) other than that it appears you're using a function pointer as if it were a function, which is probably what the compiler sees.
ta0kira
PS You shouldn't nest the *new operation here. If new fails then you have a problem, though it isn't likely new will fail, which is why you probably haven't seen a problem yet.
Applet is an abstract base class for various applets. The goal is be able to load applets from modules at runtime. Each applet is a separate class, whose definition is not present in the main program. Therefore, these applets cannot be 'new'ed, as their types are not yet fixed at compile-time. To solve this, each module exports the symbol "create_applet" a function which takes a Configuration object (we can think of these as perfectly opaque) and returns an Applet*.
"applets" is a vector of Applet*. So if we dissect this line we have, from the inside out:
((applet_creator)ptr) is casting the ptr to applet_creator, the type of the factory function pointer.
(*(new Configuration( ... ))) is passing an argument to that function pointer, a new Configuration object.
(*backings[id].first, id) is irrelevant to this discussion, it's the arguments to the Configuration's constructor
All this is then being given to the push_back method of our vector. This line creates a Configuration object, uses it to instantiate a new Applet via the factory function, then pushes that pointer onto a vector.
Hope that clears that up! Thanks for the help.
Last edited by PatrickNew; 08-24-2008 at 01:23 PM.
Reason: said "runtime" but meant "compile-time"
Oh, and the constructor for Configuration never throws, so the only time new would fail is in an out-of-memory scenario. That's not impossible, and I guess I should account for that.
But you do use a *new pattern in (*(new Configuration(...)). That's where I'm talking about. You missed my question about using a function pointer as a function. Should the cast statement be (*(applet_creator)ptr)? Am I correct in assuming that the error occurs there?
ta0kira
The warning I get is that "ANSI C++ forbids casting between pointer-to-object and pointer-to-function".
Why do you want to do this? This makes no sense. You can take function to the class function, by the way, if this is what you want.
Quote:
Originally Posted by PatrickNew
I am casting from a an object- to function-pointer intentionally. The referenced line is pulling a symbol from a dynamically loaded module via dylsym() and casting it to the appropriate function type.
This still doesn't make any sense.
If you want to access object from within loaded module, then add function to the module which will return pointer to an object.
Or access it as void*.
You probably have memory leak here, because pointer returned by new is lost, so releasing memory might be problematic.
To me it looks like you are trying to do something in a wrong way.
Explain in plain english, what are you trying to achieve.
@takoira: Oh, I see what you mean. I think that the deference operator on a function pointer is optional. That is, operator() on a function pointer calls the underlying pointer. http://www.newty.de/fpt/fpt.html#call
I still agree that the nested new's are bad form, and I will fix that. And you asked where the error occurs - it's not an error, just a warning. The code builds and runs fine, this is a more-or-less cosmetic issue. I just want to make the warning message go away the "right way".
@ErV I'm casting a void* to a function pointer because I'm dealing with runtime loadable modules. I can't just give the class a static factory function because the definition of that class doesn't exist in the program. That's what I get from the module, is the pointer to a factory function.
@ErV I'm casting a void* to a function pointer because I'm dealing with runtime loadable modules.
Casting void* to function pointer is fine. But you said you wanted to cast pointer to class into pointer to function, which is really strange request.
Quote:
Originally Posted by PatrickNew
I can't just give the class a static factory function because the definition of that class doesn't exist in the program.
What exactly do you get from module? Post it here.
Quote:
Originally Posted by PatrickNew
That's what I get from the module, is the pointer to a factory function.
How is the factory function declared? Post it here.
If it is factory, than it normally should be static class member or non-class-member function, which takes pointer as an argument, or returns pointer to a new object.
The *new is intentional, and it does not leak. The Applet object created will return a reference to it's Configuration object on request, which is deleted (via the address-of operator) when the Applet is destroyed. As Applet* is an abstract base class, and the factory functions are the only way to instantiate one, there is never an Applet on the stack - they can only be created (and thus destroyed) dynamically, and the program is structured such that all Applets are deleted at one and only one point in the code. There is a class (AppletManager) whose entire purpose is to manage the lifespans of these Applet*'s.
The new snippet is as follows:
Code:
void* ptr;
ids[name].second->get_symbol("create_applet", ptr);
//Create the applet
Configuration& c = *new Configuration(*backings[id].first, id);
applet_creator creator = reinterpret_cast<applet_creator>(ptr);
applets.push_back((*creator)(c));
The warning still appears, this time on the line with the reinterpret_cast. Hrm...
If it is factory, than it normally should be static class member or non-class-member function, which takes pointer as an argument, or returns pointer to a new object.
That's precisely what this is. It's a function which returns a pointer to a new object.
The warning still appears, this time on the line with the reinterpret_cast. Hrm...
That's because reinterpret_cast is C++'s "non-C" attempt at a C-cast; you haven't changed anything except for the cast operator used, but both operators are equivalent. Nothing actually happens with reinterpret_cast or a C-cast; you're just telling the compiler that you know what you're doing looks silly but that you want to do it anyway. You could define reinterpret_cast as this:
A leak isn't the problem: if your process runs out of memory, etc. then you'll unconditionally dereference a NULL pointer. In other words, check for NULL between new and *.
ta0kira
PS I don't see any reason why the warning should happen. This similar test works fine even with -Wall:
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.