Why doesn't MSVC initialize this const struct? - struct

I have some code written in C, and there is one section that refuses to cooperate when using Visual Studio 2015 Community (clang has no problems). I have a simple struct:
/** Options for enumerating over all documents. */
typedef struct {
unsigned skip; /**< The number of initial results to skip. */
C4EnumeratorFlags flags; /**< Option flags */
} C4EnumeratorOptions;
enum {
kC4Descending = 0x01, /**< If true, iteration goes by descending document IDs. */
kC4InclusiveStart = 0x02, /**< If false, iteration starts just _after_ startDocID. */
kC4InclusiveEnd = 0x04, /**< If false, iteration stops just _before_ endDocID. */
kC4IncludeDeleted = 0x08, /**< If true, include deleted documents. */
kC4IncludeNonConflicted = 0x10, /**< If false, include _only_ documents in conflict. */
kC4IncludeBodies = 0x20 /**< If false, document bodies will not be preloaded, just
metadata (docID, revID, sequence, flags.) This is faster if you
don't need to access the revision tree or revision bodies. You
can still access all the data of the document, but it will
trigger loading the document body from the database. */
};
typedef uint16_t C4EnumeratorFlags;
And I also have a constant "default" value for it:
// In header
extern const C4EnumeratorOptions kC4DefaultEnumeratorOptions;
// In implementation
const C4EnumeratorOptions kC4DefaultEnumeratorOptions = {
0, // skip
kC4InclusiveStart | kC4InclusiveEnd | kC4IncludeNonConflicted | kC4IncludeBodies
};
However, when debugging I noticed that the initialization is not doing anything when I try to use the default value:
// options winds up with a "skip" value of something like 117939945
// and a flags value of 59648
C4EnumeratorOptions options = kC4DefaultEnumeratorOptions;
The section defining is in a DLL, and the second using is in an exe. Again, this only happens on Windows. Furthermore, the value in "options" is garbage but for some reason it's not even the same garbage that is stored in kC4DefaultEnumeratorOptions. I know MSVC is notorious for snubbing C, but this kind of initialization is so old that even MSVC should get it right, shouldn't it? So it must be something I am doing but I can't figure out what.
EDIT The symbol is being exported via a export definitions file. I checked with dumpbin, and found the symbol in the exported symbols list
41 46 00A6EA8 kC4DefaultEnumeratorOptions = kC4DefaultEnumeratorOptions
Also as one more bit of info, the calling code is C++ and the DLL code is C, which I suspect may be playing a part in this madness.

The comments from #M.M helped put me in the right direction. He asked if the symbol was exported. Technically, yes, it was exported since it was in the export list but apparently I also need to export the definition. So instead of including the global symbol in the .def file, I need to manually mark it with __declspec(dllexport) or __declspec(dllimport) in two places so in the end it looks like this:
#ifdef _MSC_VER
#ifdef CBFOREST_EXPORTS
#define CBFOREST_API __declspec(dllexport)
#else
#define CBFOREST_API __declspec(dllimport)
#endif
#endif
// ...
// Header
CBFOREST_API extern const C4EnumeratorOptions kC4DefaultEnumeratorOptions;
// Implementation
CBFOREST_API const C4EnumeratorOptions kC4DefaultEnumeratorOptions = {
0, // skip
kC4InclusiveStart | kC4InclusiveEnd | kC4IncludeNonConflicted | kC4IncludeBodies
};

Related

Quickly (un)comment blocks of code in Rust

In languages such as Java, I often use the following pattern for quickly commenting/uncommenting whole blocks of code:
/* *
hello.world();
/* */
// I just have to add one '/' and the block is uncommented:
/* */
hello.world();
/* */
However, in Rust, the above code creates a syntax error, as it is not allowed to have unequal numbers of /* and */ in a Rust file.
But is there a similar way for quickly commenting/uncommenting blocks in Rust that does not involve using editor macro-commands?
You can use single-line comments to activate/deactivate your multi-lines comment, e.g.
/*
commented_out();
// */
//*
not_commented();
// */

Argument of function is being corrupted when function is exported in C++ when using extern "C" __declspec(dllexport)

I came across a code as follows:
#define FUNCTION_EXPORT extern "C" __declspec(dllexport)
typedef int32 (*U_Function)(HINSTANCE, const std::string &);
const char *P_FUNCTION = "processFunc";
Now this is being used in another part of same file:
int32 run(HINSTANCE instance, const std::string &cmdLine) {
try {
LibraryManager lib(PROC_LIBRARY);
FARPROC ptr = GetProcAddress(lib.getLibHandle(), U_FUNCTION);
if (ptr) {
result = reinterpret_cast<U_Function>(ptr)(instance, cmdLine);
}
.....
.....
so on
}
Now this is being used in another file .cpp of same project as following the reinterpret_cast step during debugging in visual studio in release mode:
FUNCTION_EXPORT int processFunc(HINSTANCE instance, const string &cmdLine) {
......
......
}
Here the cmdLine argument is being corrupted when function export is being used.
The cmdLine is given by user. For example if the user gives cmdLine as "None Stay" (the cmdLine was watched during debugging; as the first four bytes being randomly filled like 'su\0 and then the given argument "None Stay" follows in cmdLine) thus having only value 'su during runtime causing the application to fail.(it is being randomly generated, each time a different value following by None Stay like "¨‘\x16\x1NONE STAY etc.)
Note: The ptr and ProcessFunc have same value in run time watch.
How do we make that the user entered cmdLine argument is being successfully used during runtime and prevent the application from failing?

using a globals struct in several .cpp files, and initializing it in the constructor

I know similar questions have been asked, but none address this issue. I want to create a globals struct and initialize it with default values. I implemented it as below, but the project won't build.
I've tried everything I can think of, most notably moving the "extern" declaration of *gxg in and out of the header guard and changing the struct to a class, but get the same results: the project won't build because of duplicate symbols for the globals constructor. It builds if I don't use it in more than one .cpp file, or if I don't include a constructor or destructor in the struct's implementation file.
// globals.hpp
#ifndef globals_hpp
#define globals_hpp
struct gxGlobals{
double radius;
bool easement;
gxGlobals(); // constructor
} ;
extern "C" gxGlobals *gxg;
#endif /* globals_hpp */
—————————————
// globals.cpp
#include "globals.hpp"
gxGlobals::gxGlobals():
radius(24),
easement(false)
{};
———————————
// main_file.cpp
#include "globals.hpp"
gxGlobals *gxg = new gxGlobals();
———————————
// other_file.cpp
#include "globals.hpp"
// ERROR: Duplicate symbol gxGlobals::gxGlobals()
I can include globals.h in one file, but not in two or more. It also works if I remove the self-initialization in the .cpp file.
There are too many members in the actual struct to make an initializer list practical, so my last option is a function that runs on startup that plugs all of the default values in. Am I mistaken that this should work?

Where is ConnectEx defined?

I want to use ConnectEx function on Windows7, with MSVC2010.
I am getting error C3861: 'ConnectEx': identifier not found
MSDN suggests the function should be declared in mswsock.h, however, when checking it, it's not defined there.
Any tips?
If you read further into the MSDN article for ConnectEx() you mentioned, it says:
Note The function pointer for the ConnectEx function must be obtained
at run time by making a call to the WSAIoctl function with the
SIO_GET_EXTENSION_FUNCTION_POINTER opcode specified. The input buffer
passed to the WSAIoctl function must contain WSAID_CONNECTEX, a
globally unique identifier (GUID) whose value identifies the ConnectEx
extension function. On success, the output returned by the WSAIoctl
function contains a pointer to the ConnectEx function. The
WSAID_CONNECTEX GUID is defined in the Mswsock.h header file.
Unlike other Windows API functions, ConnectEx() must be loaded at runtime, as the header file doesn't actually contain a function declaration for ConnectEx() (it does have a typedef for the function called LPFN_CONNECTEX) and the documentation doesn't specifically mention a specific library that you must link to in order for this to work (which is usually the case for other Windows API functions).
Here's an example of how one could get this to work (error-checking omitted for exposition):
#include <Winsock2.h> // Must be included before Mswsock.h
#include <Mswsock.h>
// Required if you haven't specified this library for the linker yet
#pragma comment(lib, "Ws2_32.lib")
/* ... */
SOCKET s = /* ... */;
DWORD numBytes = 0;
GUID guid = WSAID_CONNECTEX;
LPFN_CONNECTEX ConnectExPtr = NULL;
int success = ::WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER,
(void*)&guid, sizeof(guid), (void*)&ConnectExPtr, sizeof(ConnectExPtr),
&numBytes, NULL, NULL);
// Check WSAGetLastError()!
/* ... */
// Assuming the pointer isn't NULL, you can call it with the correct parameters.
ConnectExPtr(s, name, namelen, lpSendBuffer,
dwSendDataLength, lpdwBytesSent, lpOverlapped);

trying to read iw_statistics but code wont work?

I need to read certain statistics from iw_statistics structure, here's the code:
struct net_device *dev;
struct iw_statistics *wi_stats;
dev = first_net_device(&init_net);
while (dev)
{
if (strncmp(dev->name , "wlan",4)==0 )
{
if (dev->wireless_handlers->get_wireless_stats(dev) !=NULL ) // <--- here's where the code crashes.
{
wi_stats = dev-wireless_handlers->get_wireless_stats(dev);
printk(KERN_INFO "wi_stats = dev-wireless_handlers->get_wireless_stats(dev); worked!!! :D\n");
}
}
}
I'm working on linux kernel 2.6.35 and I'm writing a kernel module. What am I doing wrong here?
Looks like wireless_handlers struct is Null ... Just because a net device has it's name field filled doesn't mean it's configured.
This is where wireless_handlers gets set:
#ifdef CONFIG_WIRELESS_EXT
/* List of functions to handle Wireless Extensions (instead of ioctl).
* See <net/iw_handler.h> for details. Jean II */
const struct iw_handler_def * wireless_handlers;
/* Instance data managed by the core of Wireless Extensions. */
struct iw_public_data * wireless_data;
#endif
You should check the value called CONFIG_WIRELESS_EXT if it's not set , the wireless_handler struct is not set and thus you''ll be pointing to a Null and your module will get stuck
You should check that dev->wireless_handlers is not null. Can you paste the actual code snippet? What is the error you get?

Resources