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

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?

Related

Unable to initialize static set of strings inside templatized class in CLang, works fine in GCC

I'm using Boost config_file_iterator to parse a parameters file for different modules in the standard Boost way:
[Module 1 name]
M1_Key1=value1
[Module 2 name]
M2_Key1=value2
For that, Boost has the nice feature to accept a std::set containing all the valid keys, to throw an exception in case a non-valid one is passed.
boost::program_options::detail::config_file_iterator cfgIt(configStream, ALLOWED_PARAMS);
In my code, I've a set of modules, each one with its own set of parameters, In each one of the module header I have (as non-member variables):
module1.h:
static const std::string MODULE1_NAME = "Module 1 name";
static const std::string MODULE1_KEY1 = "M1_Key1";
module2.h:
static const std::string MODULE2_NAME = "Module 2 name";
static const std::string MODULE2_KEY1 = "M2_Key1";
In the header file for the parameters parser:
class ParametersParser
{
static const std::set<std::string> ALLOWED_PARAMS;
}
Finally in the source file of that parameter parser groups all the allowed values for the config iterator from the different modules:
#include "module1.h"
#include "module2.h"
const std::set<std::string> ParametersParser::ALLOWED_PARAMS =
{{
MODULE1_NAME + std::string(".") + MODULE1_KEY1,
MODULE2_NAME + std::string(".") + MODULE2_KEY1
}};
since Boost expects that as the allowed parameters set, a set of string of the way "Module X Name.MX_KeyY", and that worked fine.
However, because of other reasons, I've templatized the class that parses the file, so now my set of strings is declared also in the same header file, as:
#include "module1.h"
#include "module2.h"
/* Class definition */
template <class T>
class ParametersParser
{
static const std::set<std::string> ALLOWED_PARAMS;
};
/* Static member initialization */
template <class T>
const std::set<std::string> ParametersParser<T>::ALLOWED_PARAMS =
{{
MODULE1_NAME + std::string(".") + MODULE1_KEY1,
MODULE2_NAME + std::string(".") + MODULE2_KEY1
}};
And here is where the problem arises: This compiles in both gcc 4.8.5 (CentOS 7.5 vanilla) and AppleClang 9.1.0.9020039 (MacOSX 10.3), but in MacOSX, the resulting set only contains a ".". It's like the static strings defined in the modules headers (MODULE1_NAME, MODULE1_KEY1, etc) are empty!!! In gcc/CentOS, it works fine. Unfortunately, I couldn't compile on gcc for MacOSX (It complains about unresolved dependencies with Boost), while CLang on CentOS (Apple LLVM version 9.1.0 (clang-902.0.39.2)) works fine too.
Do you have any clues what am I doing wrong? Is it something about using strings as static variables? I also tried declaring the set using the new initializer list syntax, const std::set<std::string> ParametersParser<T>::ALLOWED_PARAMS{{...}}, but didn't work either.
Thanks a lot for your help.

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?

Why doesn't MSVC initialize this const 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
};

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);

CppUnit: Run a single Test Case

In http://cppunit.sourceforge.net/doc/lastest/cppunit_cookbook.html
They give a simple TestCase but do not show how to run it (There is no main function). I've looked through their documentation and can't find how to just run a test and get text output about whether or not it succeeded. I don't want to put together a fixture or use a registry or anything.
How do I run that single test case? I.E. What is the main function that would go along with that?
I gather you were asking for a SSCCE of CppUnit. As CppUnit is a framework, so a minimal example must put minimal test structure in place -- like a TestFixture, because otherwise one could do without the whole CppUnit and just use std::assert. All this can be done in one file, say Main.cpp of the following form:
//Declaration file: MTest.h
#ifndef MTEST_H
#define MTEST_H
#include <cppunit/extensions/HelperMacros.h>
class MTest : public CPPUNIT_NS::TestFixture
{
CPPUNIT_TEST_SUITE(MTest);
CPPUNIT_TEST(simpleTest);
CPPUNIT_TEST_SUITE_END();
public:
void simpleTest();
};
#endif // MTEST_H
//////////////////////////////////////
// Implementation file, e.g. MTest.cpp
#include <cppunit/config/SourcePrefix.h>
//#include "MTest.h"
// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION(MTest);
// Some code to be tested.
void MTest::simpleTest() {
CPPUNIT_ASSERT_EQUAL(1, 2);
}
/////////////////////////////////////
// Main file, Main.cpp
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
int main(int argc, char* argv[])
{
CPPUNIT_NS::TextUi::TestRunner runner; //the runner
// Get the top level suite from the registry
CPPUNIT_NS::Test* suite =
CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest();
// Adds the test to the list of test to run
runner.addTest(suite);
// Run the test.
bool wasSucessful = runner.run();
// Return error code 1 if the one of test failed.
return wasSucessful ? 0 : 1;
}
which would need to be compiled/linked with cppunit library e.g. g++ Main.cpp ../../src/cppunit/.libs/libcppunit.a (if you happen to start 2 levels below the main directory of the library [insert the static or dynamic version of libcppunit library as is required by your environment]).
A "cleaner" examply would split the code into separate MTest (.h and .cpp, as indicated) and Main.cpp. In this case CppUnit methods from Main.cpp call methods provided by CppUnit helper macros in MTest files. They should therefore be linked together, e.g. by g++ MTest.o Main.o ../../src/cppunit/.libs/libcppunit.a.
The base class for all your test class is CppUnit::TestFixture, you can override some function like setUp and tearDown to initialize you test objects and delete them.
Consider you have a test class called MyFirstTest, to register the test functions with Cpp framework you will have to do:
CPPUNIT_TEST_SUITE(MyFirstTest);
CPPUNIT_TEST(myTestFunction);
... //any other function you want to register with appropriate macros
CPPUNIT_TEST_SUITE_END();
Also you will have to register each test class (in their respective header or cpp file)
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(MyFirstTest, "YouTestName");
Once your test class is setup, you can run it. Main function will look like:
bool wasSuccessful = false;
try
{
CppUnit::TextUi::TestRunner runner;
runner.setOutputter( new CppUnit::CompilerOutputter(&runner.result(), std::cerr));
CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry("YouTestName");
runner.addTest(registry.makeTest());
wasSuccessful = runner.run("", false);
}
catch(const std::exception& e)
{
std::cerr << e.what() << std::endl;
wasSuccessful = false;
}
If you wish to add more test classes, the main function will remain the same. You just create test class (deriving from that CppUnit::TestFixture class), register your methods and the the important step is to register you class with framework using CPPUNIT_TEST_SUITE_NAMED_REGISTRATION. The getRegistry method that is used in main function, will get all the test classes that you have registered with the framwork and executes all the methods of those classes that you have registered using CPPUNIT_TEST or any other appropriate macro.
The page you're referring to describes the whole process, including a lot of extra stuff on how you'd manually write the code in TestFixtures, then how you'd register those in TestSuites, then how you'd use the macros to write and register them, and it's very wordy. Sometimes it's better just to show people an easy example. They have this one at the very bottom of the page:
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
int main( int argc, char **argv)
{
CppUnit::TextUi::TestRunner runner;
CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
runner.addTest( registry.makeTest() );
bool wasSuccessful = runner.run( "", false );
return wasSuccessful;
}
The infrastructure is pretty simple, really. You create a test runner, then retrieve the list of registered tests, add them to the runner, have the runner run the tests, and report back to you. But yeah, it's always best to make things easy. People don't want to do hard things.
Simple but dumb solution: comment out the CPPUNIT_TEST lines you do not like.

Resources