I have a template class with a static function (see Connect function below). This template class is part of a 3rd Party lib (call it LibA). My code uses this lib and includes the header below since I need to use the template class. When I compile my lib without inline functions (-fno-default-inline with gcc) I get no problems. When I compile in release (-O2), my application crashes.
I was wondering what the implications are of having a static function in a template and how inlining may affect this.
template<class T>
class TCPConnector
: public IOHandler {
private:
string _ip;
uint16_t _port;
vector<uint32_t> _protocolChain;
bool _closeSocket;
Variant _customParameters;
public:
TCPConnector(int32_t fd, string ip, uint16_t port,
vector<uint32_t>& protocolChain, const Variant& customParameters)
: IOHandler(fd, IOHT_TCP_CONNECTOR) {
_ip = ip;
_port = port;
_protocolChain = protocolChain;
_closeSocket = true;
_customParameters = customParameters;
}
virtual ~TCPConnector() {
//FINEST("Close socket: %d", _closeSocket);
if (_closeSocket) {
close(_fd);
//FINEST("Socket closed!");
}
}
static bool Connect(string ip, uint16_t port,
vector<uint32_t>& protocolChain, Variant& customParameters) {
protoent *pProtocol = getprotobyname("IP");
if (pProtocol == NULL) {
FATAL("Unable to resolve protocol number for IP");
return 0;
}
int32_t fd = (int32_t) socket(PF_INET, SOCK_STREAM, pProtocol->p_proto);
if (fd <= 0) {
FATAL("Unable to create fd");
return 0;
}
if (!SetFdNonBlock(fd)) {
FATAL("Unable to put socket in non-blocking mode");
return false;
}
TCPConnector<T> *pTCPConnector = new TCPConnector(fd, ip, port,
protocolChain, customParameters);
if (!pTCPConnector->Connect()) {
IOHandlerManager::EnqueueForDelete(pTCPConnector);
FATAL("Unable to connect");
return false;
}
return true;
}
};
I don't think the crash is related to the fact that you use templates, statics or inlining. At least in this particular case.
You should try to find out the cause of the crash, e.g. by analyzing the dump.
You hint that you think the library contains that function. Check if it does. If so, it is definitely an error.
Check that you have the right version of the headers for your library file.
Failing that, the fix to be able to use the library would probably be to erase the definition from the header so it isn't inline any more. That would effectively make it an extern (not export) templated function, so you would only be able to use specialization(s) in the library .o.
As for what you're wondering, a static member function is linked much the same as a free function. If it's inline, it is not possible to call from the library file. Otherwise, static essentially means the same as extern: that there is only one copy, anywhere.
I agree with David Alfonso that the crash can be unrelated to the fact you use this 'library'.
Also this 'library' contains several problems not related to the crash:
It's unclear the purpose of the template parameter T. It doesn't used anywhere.
There are multiple memory and resource leaks in the Connect() method:
pProtocol and pTCPConnector are never deleted;
fd is never closed, because pTCPConnector isn't deleted.
It should not matter. A class static function is about whether you need an instance of the class to call the function or not. Effectively, the primary difference between a non-static method and a static method is the former has an extra 'hidden' function parameter.
Since you are experiencing a crash, have you identified what part of the code is actually causing the crash?
Related
Suppose I have the following:
// lib1.h
struct S
{
int x;
};
void f(S* s); // defined in .cpp
and
// lib2.h
struct S
{
int x;
int y;
};
void f(S* s); // defined in .cpp
Resulting in lib1.so and lib2.so.
So, my question is:
#include <dlfcn.h>
int main()
{
const auto lib_to_use = <some application level logic, resulting in lib1.so or lib2.so>;
const auto lib = dlopen(lib_to_use, RTLD_LAZY);
assert(lib);
const auto func = dlsym(lib, "f");
assert(func);
// how do I call `func`, given the fact it takes different, library-specific type `S`?
dlclose(lib);
}
My real-world issue is - how do I load at run-time libfuse2 or libfuse3 and execute fuse_main_real, given the fact it has fuse_operations* parameter, which is a struct with function pointers, but with different types for the two versions?
Edit: I don't believe this breaks the one-definition rule - only one of them will be linked at the same time, never both of them. (I'm also not sure if ODR is broken if both are loaded, as they are manually used, but that's another topic)
To the extent that the standard can be said to apply to dynamic objects, you’re right that there’s no ODR violation between multiple objects that are never loaded together (because there is no program that contains both definitions). The same cannot be said for your program if it contains a definition of each class type (obviously) or contains a definition of one and (the runtime choice is that it) loads the dynamic object that uses the other. (With DLLs the situation is stranger: types are shared but not their member functions, static data members, or RTTI symbols.)
The answer is to keep those definitions separate: wrap each dynamic object in one of your own (linked against it with a simple -l) that exposes a common interface (which must be possible for the question to make sense). Load one or the other of those in your main program and call it using the unique type(s) #included from that interface.
how do I call func, given the fact it takes different, library-specific type S?
Obviously you can't have type S in your main program that matches both lib1 S and lib2 S at the same time. So you must declare two separate types: S1 and S2.
The rest is trivial:
int version = which_version_should_I_use();
if (version == V1) {
void *h = dlopen("lib1.so", RTLD_LAZY);
void (*fn)(S1*) = (void (*)(S1*))dlsym(h, "f");
assert(fn != NULL);
S1 s = ...;
fn(&s);
} else {
// must be V2
void *h = dlopen("lib2.so", RTLD_LAZY);
void (*fn)(S2*) = (void (*)(S2*))dlsym(h, "f");
assert(fn != NULL);
S2 s = ...;
fn(&s);
}
Consider the following code:
file_1.hpp:
typedef void (*func_ptr)(void);
func_ptr file1_get_function(void);
file1.cpp:
// file_1.cpp
#include "file_1.hpp"
static void some_func(void)
{
do_stuff();
}
func_ptr file1_get_function(void)
{
return some_func;
}
file2.cpp
#include "file1.hpp"
void file2_func(void)
{
func_ptr function_pointer_to_file1 = file1_get_function();
function_pointer_to_file1();
}
While I believe the above example is technically possible - to call a function with internal linkage only via a function pointer, is it bad practice to do so? Could there be some funky compiler optimizations that take place (auto inline, for instance) that would make this situation problematic?
There's no problem, this is fine. In fact , IMHO, it is a good practice which lets your function be called without polluting the space of externally visible symbols.
It would also be appropriate to use this technique in the context of a function lookup table, e.g. a calculator which passes in a string representing an operator name, and expects back a function pointer to the function for doing that operation.
The compiler/linker isn't allowed to make optimizations which break correct code and this is correct code.
Historical note: back in C89, externally visible symbols had to be unique on the first 6 characters; this was relaxed in C99 and also commonly by compiler extension.
In order for this to work, you have to expose some portion of it as external and that's the clue most compilers will need.
Is there a chance that there's a broken compiler out there that will make mincemeat of this strange practice because they didn't foresee someone doing it? I can't answer that.
I can only think of false reasons to want to do this though: Finger print hiding, which fails because you have to expose it in the function pointer decl, unless you are planning to cast your way around things, in which case the question is "how badly is this going to hurt".
The other reason would be facading callbacks - you have some super-sensitive static local function in module m and you now want to expose the functionality in another module for callback purposes, but you want to audit that so you want a facade:
static void voodoo_function() {
}
fnptr get_voodoo_function(const char* file, int line) {
// you tagged the question as C++, so C++ io it is.
std::cout << "requested voodoo function from " << file << ":" << line << "\n";
return voodoo_function;
}
...
// question tagged as c++, so I'm using c++ syntax
auto* fn = get_voodoo_function(__FILE__, __LINE__);
but that's not really helping much, you really want a wrapper around execution of the function.
At the end of the day, there is a much simpler way to expose a function pointer. Provide an accessor function.
static void voodoo_function() {}
void do_voodoo_function() {
// provide external access to voodoo
voodoo_function();
}
Because here you provide the compiler with an optimization opportunity - when you link, if you specify whole program optimization, it can detect that this is a facade that it can eliminate, because you let it worry about function pointers.
But is there a really compelling reason not just to remove the static from infront of voodoo_function other than not exposing the internal name for it? And if so, why is the internal name so precious that you would go to these lengths to hide that?
static void ban_account_if_user_is_ugly() {
...;
}
fnptr do_that_thing() {
ban_account_if_user_is_ugly();
}
vs
void do_that_thing() { // ban account if user is ugly
...
}
--- EDIT ---
Conversion. Your function pointer is int(*)(int) but your static function is unsigned int(*)(unsigned int) and you don't want to have to cast it.
Again: Just providing a facade function would solve the problem, and it will transform into a function pointer later. Converting it to a function pointer by hand can only be a stumbling block for the compiler's whole program optimization.
But if you're casting, lets consider this:
// v1
fnptr get_fn_ptr() {
// brute force cast because otherwise it's 'hassle'
return (fnptr)(static_fn);
}
int facade_fn(int i) {
auto ui = static_cast<unsigned int>(i);
auto result = static_fn(ui);
return static_cast<int>(result);
}
Ok unsigned to signed, not a big deal. And then someone comes along and changes what fnptr needs to be to void(int, float);. One of the above becomes a weird runtime crash and one becomes a compile error.
I am writing an adapter to combine two APIs (one in C and another in C++).
If a function is called on the one API I need to pass the callers ID and the function's arguments to an adapter and call the according function with this information passed.
Now aparently they can not be mapped directly as one interface requires C++ compilation and the name mangling would screw the other so that is why I am using a set of adapters in the first place.
As the number of arguments varies, I looked up variadic functions and found the idea pretty useful, however I am operating on POD only and have to deal with structs, enums and a lot of different arguments per call, which might need to be put back into a struct before feeding it to the target function.
Every example I stumbled upon was far simpler and involved mostly arithmetic operations like summing stuff up , finding largest numbers or printing. Mostly done with for loops on the var_list.
Maybe I got stuck on the idea and it won't work at all, but I am just curious...
Say I wanted to assign the arguments from the list to my target functions parameters (the order of the arguments passed is the correct one), what would be a good way?
BOOL Some_Function(
/* in */ CallerId *pObjectId,
/* in */ someDataType argument1 )
{
BOOL ret = Adapter_Call(pFunction, pObjectId, argument1);
return ret;
}
and so once I made it to the right adapter I want to do
BOOL Adapter_Call(*pFunction, *pObjectId, argument1, ...)
{
va_list args;
va_start(args, argument1);
/*go over list and do `var_list[i] = pFunctionArgList[i]` which is
of whatever type so I can use it as input for my function */
va_end(args);
pObjectId.pFunction(arg1,...,argn);
}
Can I access the input parameters of a function to perform assignments like this?
Has anyone done something like this before? Is there a conceptual mistake in my thinking?
All I found on the net was this, http://www.drdobbs.com/cpp/extracting-function-parameter-and-return/240000586but due to the use of templates I am not sure if it wouldn't create another problem and so in the end implementing an adapter for each and every single functioncall may be simpler to do.
A SO search only returned this: Dynamic function calls at runtime (va_list)
First, you should heed Kerrek's advice about extern "C". This is C++'s mechanism for giving an identifier C linkage, meaning that the name won't be mangled by the C++ compiler.
Sometimes, and adapter still needs to be written for a C++ interface, because it manipulates objects that do not map to a C POD. So, the adapter gives the C interface a POD or opaque pointer type to manipulate, but the implementation of that interface converts that into an C++ object or reference and then calls the C++ interface. For example, suppose you wanted to provide a C interface for C++ std::map<int, void *>, you would have a common header file in C and C++ that would contain:
#ifdef __cplusplus
extern "C" {
#endif
struct c_map_int_ptr;
// ...
// return -1 on failure, otherwise 0, and *data is populated with result
int c_map_int_ptr_find (struct c_map_int_ptr *, int key, void **data);
#ifdef __cplusplus
}
#endif
Then, the C++ code could implement the function like:
typedef std::map<int, void *> map_int_ptr;
int c_map_int_ptr_find (struct c_map_int_ptr *cmap, int key, void **data) {
map_int_ptr &map = *static_cast<map_int_ptr *>(cmap);
map_int_ptr::iterator i = map.find(key);
if (i != map.end()) {
*data = i->second;
return 0;
}
return -1;
}
Thus, there is no need to pass the arguments passed via the C interface through a variable argument adapter. And so, there is no need for the C++ code to tease out the arguments from a variable argument list. The C code calls directly into the C++ code, which knows what to do with the arguments.
I suppose if you are trying to implement some kind of automated C adapter code generator by parsing C++ code, you could think that using variable arguments would provide a regular mechanism to communicate arguments between the generated C code interface and the generated C++ adapter code that would call the original C++ interface. For such a scenario, the code for the above example would look something like this:
// C interface
typedef struct c_map_int_ptr c_map_int_ptr;
typedef struct c_map_int_ptr_iterator c_map_int_ptr_iterator;
//...
c_map_int_ptr_iterator c_map_int_ptr_find (c_map_int_ptr *map, int key) {
c_map_int_ptr_iterator result;
cpp_map_int_ptr_adapter(__func__, map, key, &result);
return result;
}
// C++ code:
struct cpp_adapter {
virtual ~cpp_adapter () {}
virtual void execute (va_list) {}
};
void cpp_map_int_ptr_adapter(const char *func, ...) {
va_list ap;
va_start(ap, func);
cpp_map_int_ptr_adapter_method_lookup(func).execute(ap);
va_end(ap);
}
//...
struct cpp_map_int_ptr_find_adapter : cpp_adapter {
void execute (va_list ap) {
map_int_ptr *map = va_arg(ap, map_int_ptr *);
int key = va_arg(ap, int);
c_map_int_ptr_iterator *c_iter = va_arg(ap, c_map_int_ptr_iterator *);
map_int_ptr::iterator i = map->find(key);
//...transfer result to c_iter
}
};
Where cpp_map_int_ptr_adapter_method_lookup() returns an appropriate cpp_adapter instance based on a table lookup.
As previously discussed here, I'm trying to find a workaround for the LNK2019 issue that arises when building a static library which utilizes C++ templates, and separating the source from the header to keep the code private from other projects. I believe I've nearly come to a working conclusion (for my particular situation), but I'm not entirely sure if this is the correct/best way to go about it and was wondering if anyone has any suggestions, improvements/comments to add?
The goal is to do some type checking to see if the template's signature matches the target prototype function's signature, do some private processing, and return whether or not it was sucessful. NOTE that I have removed SdkHookMgr.h and SdkHookMgr.cpp from the prior version of the solution in the above link, and merged everything back into SdkLib.h and SdkLib.cpp, into a static class for a bit of clarity.
SdkLib.h:
#include <typeinfo>
#ifdef MY_EXPORTS
# define MYDECL __declspec(dllexport)
#else
# define MYDECL
#endif
// Prototypes
typedef HMODULE (WINAPI *HookLoadLibraryA)( LPCSTR lpFileName );
//...
class CHook;
class CHookManager;
MYDECL BOOL WINAPI ValidateHook( CHook *hook );
class CHook
{
public:
CHook() : m_type(NULL), m_target(NULL), m_result(FALSE) {};
CHook( const char *type, PVOID target ) : m_type(type), m_target(target) {
m_result = ValidateHook(this);
};
const char *m_type;
PVOID m_target;
BOOL m_result;
};
class CHookManager
{
public:
template <typename HookFunction> static BOOL Hook(HookFunction target)
{
const type_info& type = typeid(HookFunction);
CHook *hook = new CHook( type.name(), target );
return hook->m_result;
}
};
SdkLib.cpp:
#include <SdkLib.h>
IDXDECL BOOL WINAPI ValidateHook( CHook *hook )
{
// Do type checking, private processing, etc here...
return TRUE;
}
DemoDLL.cpp:
#include <SdkLib.h>
HMODULE WINAPI Hooked_LoadLibraryA( LPCSTR lpFileName )
{
DebugBreak();
}
// The function that starts the rollercoaster.
// - Syntax: Hook< prototype >( target )
if!(CHookManager::Hook<HookLoadLibraryA>(Hooked_LoadLibraryA))
cout << "Failed to create hook for LoadLibraryA!" << endl;
You may find that the results of typeid are not consistent between the DLL and the main program. (See, for example, typeid result across different dll's.)
Since your list of possible hooks is limited, it strikes me that overloaded functions would be a better choice than templates. You'd then have no DLL issues, and the validity of each hook would be checked at compile time. Here's an example of the sort of thing I'm thinking of; obviously in practice you'd split this into separate definition and declaration, with the definitions living in the DLL so it's all cleanly separated out.
class CHookManager {
public:
BOOL Hook(HookLoadLibraryA hook) {
assert(sizeof hook<=sizeof(uintptr_t));
return ValidateHook((uintptr_t)hook,"LoadLibraryA");
}
BOOL Hook(HookLoadLibraryW hook) {
assert(sizeof hook<=sizeof(uintptr_t));
return ValidateHook((uintptr_t)hook,"LoadLibraryW");
}
};
(Note that this shows up one disadvantage of this approach - you can only have one hook per function signature. I mention this for completeness' sake, but I'll assume this hasn't proven an issue.)
(You might like to replace the assert with a compile-time assert, if you have one.)
ValidateHook would use strcmp to figure out which hook is being hooked. Once it's figured out which hook it is, it would then cast the uintptr_t to the appropriate function pointer type. It knows the pointer was originally of the correct type for that hook, because you're using the C++ overload mechanism to do it all. (Or you could have an enum, say, for all the hook types, rather than passing in a string - it's up to you. The key part is that you have full control over the values being passed, so that the DLL and the calling code are definitely using matching values.)
This code would be a little tiresome to generate, but if you already have the list of typedef names then you could create the corresponding code using regular expression search and replace, or keyboard macros, in your editor of choice. Or you could use something like the so-called "X-Macro" to automate the generation of the whole thing.
I'm having some weird issues with static initalization. I'm using a code generator to generate structs and serialization code for a message passing system I wrote. In order to have a way of easily allocating a message based on it's message id I have my code generator ouput something similar to the following for each message type:
MessageAllocator s_InputPushUserControllerMessageAlloc(INPUT_PUSH_USER_CONTROLLER_MESSAGE_ID, (AllocateMessageFunc)Create_InputPushUserControllerMessage);
The MessageAllocator class basically looks like this:
MessageAllocator::MessageAllocator( uint32_t messageTypeID, AllocateMessageFunc func )
{
if (!s_map) s_map = new std::map<uint32_t, AllocateMessageFunc>();
if (s_map->insert(std::make_pair(messageTypeID, func)).second == false)
{
//duplicate key!
ASSERT(false, L"Nooooo!");
}
s_count++;
}
MessageAllocator::~MessageAllocator()
{
s_count--;
if (s_count == 0) delete s_map;
}
where s_map and s_count are static members of MessageAllocator. This works most of the time but sometimes messages are not added to the map. For example, this particular message is not added unless i call Create_InputPushUserControllerMessage() somewhere in my startup code, however other messages work fine. I thought this might be something to do with the linker incorrectly thinking the type is unreferenced and removing it so I disabled that using the /OPT:NOREF switch (I'm using Visual Studio 2008 SP1) but that had no effect.
I'm aware of the problem of the "static initialization order fiasco" but as far as I know the order in which these objects are created shouldn't alter the result so this seems ok to me.
Any insight here would be appreciated.
Put the static into a class so it is a static member of a class
struct InputPushUserControllerMessageAlloc { static MessageAllocator s_obj; };
MessageAllocator InputPushUserControllerMessageAlloc::s_obj(
INPUT_PUSH_USER_CONTROLLER_MESSAGE_ID,
(AllocateMessageFunc)Create_InputPushUserControllerMessage);
The Standard allows it to delay initialization of objects having namespace scope until any function/object from its translation unit is used. If the initialization has side-effect, it can't be optimized out. But that doesn't forbid delaying it.
Not so of objects having class-scope. So that might forbid it optimizing something there.
I would change s_map from a static class member into a static method member:
std::map<uint32_t,AllocateMessageFunc>& MessageAllocator::getMap()
{
// Initialized on first use and destroyed correctly on program termination.
static std::map<uint32_t,AllocateMessageFunc> s_map;
return s_map;
}
MessageAllocator::MessageAllocator( uint32_t messageTypeID, AllocateMessageFunc func )
{
if (getMap().insert(std::make_pair(messageTypeID, func)).second == false)
{
//duplicate key!
ASSERT(false, L"Nooooo!");
}
}
No need for destructor or a count.
If your global objects are in separate DLL's(or shared libs) that are lazy loaded.
This may cause a problem similar to your description.
You are not setting the pointer back to null.
MessageAllocator::~MessageAllocator()
{
s_count--;
if (s_count == 0)
{
delete s_map;
s_map = 0;
}
}
Turns out that the object files containing the static initializers were not included by the linker because nothing referenced any functions in them. To work around this I extern "C"-ed one of the generated functions so that it would have a predictable non-mangled name and then forced a reference to it using a pragma like this for each message
#pragma comment(linker, "/include:Create_GraphicsDynamicMeshCreationMessage")
which I put in the generated header file that is later included in all the other non-generated files. It's MSVC only and kind of hack but I assume I can do something similar on GCC once I eventually port it.