Global Static Pointer Issue - visual-c++

This is a rather a problem from a convoluted situation. I have a static pointer sitting in one of my header files. Which is being included everywhere, this is why I put it as a static pointer. So that I can quickly initilize it in my main function so that other files can use it.
The problem is this, even after I initialize it and put stuff into it. Other files only find it NULL. It is like every file that includes the header with the static pointer makes a copy of it for itself and even when others initialize it, each file has their own separate copy. Negating ofcourse, the purpose of having a global variable.
How can I cope up with this?. Maybe I am understanding a static variable wrong, or maybe is it because its a pointer?
Should i be declaring it as: &variable = 5; or just as variable = 5; or &variable = (int)5?

It is like every file that includes the header with the static pointer makes a copy of it for itself and even when others initialize it, each file has their own separate copy.
That's what static means when applied to a variable at namespace scope: the variable is given internal linkage, making it "local" to a given translation unit (source file).
If you have a static variable at namespace scope in a header file and you include that header file in multiple .cpp files, there will be multiple instances of that variable: one for each of the .cpp files that include the header file.
If you want a global variable that is shared across multiple source files, you need to make it extern. Declare the variable as extern in the header file, then define the extern variable in exactly one of your .cpp files.

Yes, you are understanding the static keyword wrong. Static keyword at namespace and file scope declares a variable that is only visible inside the translation unit (basically a single .cpp file plus all of its includes) where it is declared. By declaring a static variable in header that you use in multiple .cpp files you are effectively defining multiple variables.
If you want a global pointer then declare it extern without static in the single header and define it without extern or static in a single .cpp file. E.g.:
In foo.h:
extern int * p;
and in main.cpp:
int * p = something;

Defining the global pointer static results in the C++ compiler creating a separate pointer for every translation unit, the definition is included in. I'm pretty sure it's not what you want and it's the cause of your problems.
You should declare it extern in a header and define once in one cpp file.
I can imagine the confusion came from the way, static keyword works inside a class or a struct definition. Indeed, it works differently there and it creates one variable, common for all instances of the class or struct.
Btw. In case you actually want a variable to be visible only in one translation unit the recommended way is to put ii into an anonymous namespace. static works too, but it's use is discouraged as deprecated.

Related

How to inline assembly into file scope passing Rust-defined constants?

I need the same behavior as the global_asm! macro, but passing constants defined in my Rust code. The obvious choice would be to use a (private) naked function that contains inline asm! instruction, but I don't see any way to prevent such a function from being removed by linker as unused. Can you suggest a proper way of doing that?

How do decorated names get into import libraries when I only provide the undecorated name?

I'm working in Visual C++, VS2015 Community. I've written this tiny little DLL:
#include "stdafx.h"
int showMsgBox(wchar_t* caption, wchar_t* message)
{
MessageBox(NULL, message, caption, 0);
return 0;
}
And this tiny little client:
#include "stdafx.h"
__declspec(dllimport) int showMsgBox(wchar_t* caption, wchar_t* message);
int main()
{
showMsgBox(L"SimpleDLLClient", L"Hello DLL World!");
return 0;
}
To export the showMsgBox function, I've created this module definition file:
LIBRARY SimpleDLL
EXPORTS
showMsgBox
When I link my client, I pass it the import library that was created when I linked my DLL. Everything compiles and links fine.
And that puzzles me.
According to MSDN, "Because the Visual C++ compiler uses name decoration for C++ functions, you must either use the decorated name as the entryname or internalname, or define the exported functions by using extern "C" in the source code."
But I'm not exporting a decorated name, am I?
If, instead of using a module definition file, I were to prefix the function with the __declspec(dllexport) extended attribute, I wouldn't be surprised (as this ought to have whatever name decoration the compiler applies match the same decoration applied by the compiler to the client).
Likewise, if I prefixed the function with 'extern "C"' in both the DLL and client code, that should also work (and it does: I tested it), because, again, the symbols should match.
But, I would have expected an undecorated export in the module definition file to fail to resolve the client's reference to the same undecorated name, when neither the DLL nor client code uses 'extern "C",' which seems also to be what MSDN says I should expect. Yet, exporting the undecorated name via the module definition file does work, even when I do not use 'extern "C"' anywhere.
Can anyone tell me why this works?
UPDATE
Looking into the files created by the linker, I see that putting the undecorated name into the module definition file apparently results in the decorated name being included in the import library. When I use dumpbin /exports on that file, here's what I get:
File Type: LIBRARY
Exports
ordinal name
?showMsgBox##YAHPEA_W0#Z (int __cdecl showMsgBox(wchar_t *,wchar_t *))
Now, somewhat amazingly (to me, anyway), if I explicitly alias the decorated name, like this:
LIBRARY SimpleDLL
EXPORTS
showMsgBox=?showMsgBox##YAHPEA_W0#Z
dumpbin tells me that this is what shows up in the import library:
File Type: LIBRARY
Exports
ordinal name
showMsgBox
Using that as input to the linker when I build the client works fine too, provided that I use 'extern "C"' when I declare my imported function:
extern "C" int showMsgBox(wchar_t* caption, wchar_t* message);
That makes sense, since the symbol the linker is now looking for is the undecorated "showMsgBox," and I have aliased that symbol to the decorated name created when I compiled my DLL.
Soooo...
What it looks like to me is that pages and pages of MSDN documentation that all say you must use decorated names in module definitions files are mistaken. Rather, it appears that if you use the undecorated name in your module definition file, it is the decorated name that is actually incorporated into your import library, which will resolve the reference to the matching decorated name constructed when you compile your client code. That, of course, is what I would prefer, rather than having to extract the decorated names and use those in my module definition files. It just doesn't match what the MSDN pages repeatedly say.
I like to think I'm a bright boy, but it's pretty arrogant of anyone to suggest that Microsoft doesn't know how its own products work.
What am I missing here?
UPDATE 2
With the DLL and client both using decorated names (that is, no use of 'extern "C"' anywhere), everything builds fine with the undecorated name in the module defintion file, like I said. But, interestingly, with no changes at all to the source code, things build equally well if I do use the decorated name in the module definition file:
LIBRARY SimpleDLL
EXPORTS
?showMsgBox##YAHPEA_W0#Z
At the binary level, the import library this creates is nearly identical to the library created when I use the undecorated name in the module definition file. The only differences appear to be time-stamps, with the exception of one byte near the end. Still trying to make sense of that one, but it appears ever more certain that, somehow, the linker is exporting the decorated name, even when the module definition file refers solely to the undecorated name.

Include once capability in Inno Setup Preprocessor?

I am creating a library of script methods and only want to include them when needed in my installers.
Some of the methods need to use other methods so I was putting the #include "filename.iss" for the needed methods in the file with the method that needs it.
However, if I include two files in an installer script file that also include a common file I get a "Duplicate identifier" error in the second file that includes it.
I've searched for something like #include-once but can't find any results for it.
To reproduce you can just include the same file twice:
#include "AddReplaceLinesInFile.iss"
#include "AddReplaceLinesInFile.iss"
The only way I can see to avoid this is to not put the includes in the files with the methods that need them and just add them in the main installer script.
I'm leaving the includes in the top of the method files that need them but commenting them out - for documentation purposes and to make it easy to copy and paste them into my main installer script. However I'd prefer to use something like an include-once capability.
Does Inno Setup have anything like include-once or a way to test for an already defined method so I could create something similar?
TIA
Use the same trick as is used in C/C++, the include guard:
In the C and C++ programming languages, an #include guard, sometimes called a macro guard, is a particular construct used to avoid the problem of double inclusion when dealing with the include directive.
Surround the code in the included file with #ifndef UniqueName, #define UniqueName ... #endif:
#ifndef IncludeIss
#define IncludeIss
procedure Test;
begin
end;
#endif
The UniqueName is typically the same as filename, with punctuation removed (to make it a valid identifier). I.e. for include.iss the name can be IncludeIss.
See Inno Setup Preprocessor: #ifdef, #ifndef, #ifexist, #ifnexist.
There is no such thing as include-once.
Inno Setup is Pascal based where functions (and procedures) are global! There are no private ones.
Preprocessor Symbols are scoped to the .iss file and to make them global use public keyword.
Variables have really unpleasant behavior: if you define global variable (in [Code] section) with the same name as local variable you never know into which variable the value is really assigned.
Compiler does not check this which is really bad.

Main Program and Shared Library initializes same static variable in __static_initialization_and_destruction_0

Does anyone know why a library initialized within dlopen() would initialize a static variable owned by the main program. Both the main program and shared library have a copy of the static variable, but for some reason the shared library re-initializes the main program's copy of the static variable and destructs it, causing a segfault when the main program attempts to destruct it.
Is this a case of bad name mangling in the symbol table?
This is a case where the runtime linker only wants a single active copy of a symbol in a process. If both a shared object and the executable have a copy of the symbol, the runtime linker will resolve all references to one of those.
What you can do to solve this problem is to use symbol reduction using the version command of the link editor when building the shared object. Make sure the symbol for the static variable is not global and you will get the behavior you are looking for.

Link errorLNK2005 in VC++

I have a programme I which I want to implement button class. I have declared all my variable in button.h and defined all methods in button.cpp and I am calling these functions in WINMAIN the following error appears.
keylogger.obj : error LNK2005: "struct HBITMAP__ * hOldBmp" (?hOldBmp##3PAUHBITMAP__##A) already defined in Button.obj
The error is for multiple defination hOldBmp but It is only defined in button.h
"Only defined in button.h" is exactly your problem. Unless you declared it as extern there and put the definition into a C++ source file (not header file), every translation unit will get their own definition of the variable.
Seems like a common error: you include the implementation of this hOldBmp pointer from two .obj files, so from two cpp files. So both obj files contain code to implement this pointer. The linker cannot decide which implementation to use in the final binary.
Solution: leave only the declaration in the header file. You may declare it extern or make it a static member variable of the button class. Put the definition in the cpp file.

Resources