I have a dll that someone made me in C++. I needed to use this dll in VB, in order to do that I had to make another dll in C++ that has functions I can call in VB.
The C++ dll I made has 4 functions. 2 callback functions that retrieve information from the original C++. And 2 functions that I can call from VB to send that information.
I know the original dll works fine as Ive tested it endlessly in a console app.
However when I use it with my dll and VB.. I get random crashes.
There is almost no code in my VB app as its just for testing. It just outputs the information so theres no problem there.
I believe the problem is in the C++ dll I made. I am pretty new with C++.
I think maybe a variable gets accessed in 2spots at the same time (is this possible?) and causes it to crash?
Heres the basic layout of my C++ dll
//global variables
CString allInfo="";
char* info=new char[25000];
//call back function 1
HANDLE OnInfo(SendInfo* tempInfo)
{
CString stringTemp="";
stringTemp=tempInfo->infomessage;
allInfo=allInfo+ stringTemp+"\n";
return 0;
}
//function for vb
BSTR _stdcall vbInfo()
{
allInfo=allInfo.Right(20000); //get last 20,000 characters
strcpy_s(info,20000,allInfo);
BSTR Message;
Message = SysAllocStringByteLen (info, lstrlen(info));
return Message;
}
Crash seems to happen completely randomly.
Any suggestions?
Thanks
Aside from learning that Googling for the CString class reference returns some ahem interesting results, your problem is probably going to be the multiple access of CString.
You didn't post a lot of info, so I'm going to assume the OnInfo method is a callback function that is called by a thread of execution different from the one that calls vbInfo. In this case, you want to look at the CString::operator=() method description on MSDN:
The CString assignment (=) operator reinitializes an existing CString
object with new data. If the destination string (that is, the left
side) is already large enough to store the new data, no new memory
allocation is performed. You should be aware that memory exceptions
may occur whenever you use the assignment operator because new storage
is often allocated to hold the resulting CString object.
Given that there does not appear to be a limit on the size of what you put into the CString, it may be deallocating and allocating the memory in allInfo in one function while you're reading or writing it in another functions. Things don't go so well when you suddenly try to write to unallocated memory.
You might want to look at something like a Critical Section or a mutex to keep both of your functions from hosing the common memory buffer.
You didn't say if your dll is compiled to use Unicode or ANSI strings. You didn't say if the dll that the other person supplied to you is compiled to use Unicode or ANSI strings. The VB caller probably gives you Unicode strings, but it is possible to make the VB caller give you ANSI strings. So we see your code with CString of unknown type, char* pointing to an ANSI string, BSTR pointing to a Unicode string but size allocated in bytes, and who knows what.
There are a lot of articles explaining how to use Unicode, but they'd be a bit too heavy for someone who is pretty new to C++.
It would really be best if you go back to the person who made the other dll for you, and ask that person to add features that you need. Also mention to them that you'll be calling the dll from VB, so you need their dll to handle Unicode strings.
Related
I am fairly new to C++ and working with DLLs. I have a main application that aggregates results from different measurements. As the measurements are different from case to case I decided to put them into external DLLs so they can be loaded at runtime (they simply all export the same function). The idea is to just load them like this so the aggregator can be extended depending on the runtime needs:
typedef int (*measure)(measurement &dataHolder);
int callM() {
[...]
measurement dataHolder;
lib = LoadLibraryA("measureDeviceTypeA.dll");
measure measureFunc = (measure)GetProcAddress(lib, "measureFunc");
pluginFunc(dataHolder);
[...] // close the lib and load the next one depending on found Devices
}
This works pretty well for simple datatypes (depending on the actual definition of the struct "measurement") such as this:
typedef struct measurement {
DWORD realPBS;
DWORD imaginaryPBS;
int a;
} measurement;
Now there also may be a string of arbitrary length (char representations of results). I would like to put them into the measurement struct as well and fill them inside the actual worker function inside the DLL. My first assumption was that it would be easy to just use std::string, which works sometimes and sometimes not (as it will reallocate memory on std::string().append() and this might break (access violation) depending on the actual runtime environment of the program and the dll). I read here and here that returning a string from a function is a bad idea.
So what would be the "proper" C++ way of returning arbitrary length strings from such a call? Is it helpful at all to pass a struct to the DLL or should I split it into separate calls? I don't want to have pointers dangling around or unfreed memory when I close the DLL again.
This won't work with std::string, as noted by Dani in the comments. The problem is that std::string is a type that belongs to your implementation, and different C++ implementations have different std::strings.
For DLL's specifically (Microsoft), you do have another alternative. COM is an ancient technology, but it still works today and is unlikely to go away ever. And it has its own string type, BSTR. Visual Studio provides a helper C++ class bstr_t for your own code, but on the interface you'd use the plain BSTR from _bstr_t::GetBSTR.
BSTR relies on the Windows allocator SysAllocString from OleAut32.dll
The problem is, that the string data is often allocated on the heap, so it has to be freed / managed somehow.
You could think, hey std::string is returned by value - so why I need to care about memory management. The problem is that usually only very small strings are stored "inside" the class. For larger strings the string class contains a pointer to some "heap-storage".
Dlls can be used from and with different programming languages - which is the reason that dlls do not share a "memory manager", freeing in the dll would fail.
To solve this you need to have two function calls, one which returns a pointer / handle to the data and one to free it. Or the caller could give the callee some pointer where it wants the data to be stored. You need for that a maximum-byte-count, too.
As you can see, there are some reasons why you should avoid these APIs - but it is not always possible. See for example the Windows API (there you can find both approaches).
Another approach would be to ensure a shared memory manager, but this is tricky somehow because it must be done really early!
I'm new to c++ and Access. I'm working with a project calls dll (compiled by c++) from Access.
I want to understand how are the parameters passed into the dll.
The input data for dll is prepared in Access, and we call the dll from Access.
We associate "RunFunction" with the dll we want to call.
The line in Access calls the dll:
Results = RunFunction(Data.age, Data.calendar, Data.timesheet, Data.extra)
The cpp code that complies the dll:
double __stdcall RunFunction(double * iData, double(*iCalendar)[100], double(*iTimesheet)[100])
First question, from the cpp code, I found the *iData(in c++) actually contains all info from Data (in Access).
Why it could happen? I thought only Data.age is passed into *iData, not the whole Data?
Second question, the the RunFunction from Access has four input parameters, while c++ only takes three, why it doesn't this cause any issue?
First, consider that inside Access the value of Data.age might be inside a buffer containing the entire record or some other structure. So when the address of that one value is passed to you in C++, you can explore neighboring addresses and see what’s in it. Don’t do that!
Second, look at the way __stdcall works. It was designed in the early days of C when function arguments were not checked at all! You can pass fewer or more parameters on the caller side and not mess up the stack. If you pass extra, no big deal. If you leave off some, then using the rightmost names in the function will give garbage values and witing to them can cause all sorts of problems including clobbering the return address.
I am trying to make a DLL that exposes a certain API and thus wanted to implement a safe way to copy strings over the DLL boundaries. The DLL implementation is very straight forward - all the functions that return string values take two arguments - char* and size_t&. If the size is big enough I memcpy the contents of the string from within the DLL to the given pointer, set the size to the actual one and return a successful return code. If it is not I set the size to what it should be and return an error code. The DLL side is very straightforward.
Now what is more complicated - how to make a nice template function which given a pointer to some function from the DLL would do all the correct manipulations to fill out an instance of std::string. This is what I came down to:
template<typename I>
CErrorCode GetStringValue(const I& Instance, CErrorCode(I::*pMethod)(char*, size_t&) const, std::string& sValue)
{
std::string sTemporaryValue;
size_t nValueLength = sTemporaryValue.capacity();
sTemporaryValue.resize(nValueLength);
do
{
auto eErrorCode = (Instance.*pMethod)(const_cast<char*>(sTemporaryValue.c_str()), nValueLength);
if (eErrorCode == CErrorCode::BufferTooSmall)
{
sTemporaryValue.resize(nValueLength);
}
else
{
if (eErrorCode == CErrorCode::NoError)
{
sTemporaryValue.resize(nValueLength);
sValue = std::move(sTemporaryValue);
}
return eErrorCode;
}
}
while (true);
}
So I did the initial resize because I can't do that after the first call (since then it would erase the content, since the string is initially empty). But resize fills the string with zero characters, which kind of upsets me (I mean I know I am going to be doing the filling myself anyway). And then I need the resize even after a successful run since if the length was actually smaller I need to resize down. Any suggestions if this can be done I a nicer way?
Since you are using DLLs, my understanding is that you are on Windows, so I'm going to suggest a Windows-specific solution.
Well, the problem of safely passing string across module boundaries has already been solved on Windows by COM memory allocator and BSTR.
So, instead of passing a string pointer and a size pointer, and check if the caller's allocated buffer is large enough, and if not return the required size, etc. it seems much simpler to me to just return BSTRs from the DLL.
BSTRs are allocated using a COM allocator, and so you can allocate them and free them across different module boundaries.
There are also nice C++ wrapper classes around a BSTR, e.g. _bstr_t or ATL's CComBSTR. You can use those at the caller's site.
Once you have a BSTR instance, possibly properly wrapped in a convenient RAII wrapper at the caller's site, you can easily convert it to a std::wstring.
Or, if you want to use the Unicode UTF-8 encoding and std::string, you can convert from the BSTR's native UTF-16 encoding to UTF-8, using WideCharToMultiByte() (this MSDN Magazine article can come in handy).
Bonus reading: Eric’s Complete Guide To BSTR Semantics
P.S.
If you don't want to use the BSTR type, you can still use a common memory allocator provided by COM: e.g. you can allocate your (UTF-8) string memory using CoTaskMemAlloc() in the DLL, and free it using CoTaskMemFree() at the caller's site.
Let me start off by saying it's been several years (over 8) since I have had to mess with C++. I am very rusty again and it looks like I'll have to start doing some side projects to get the hang of it.
I know this is really simple and I'm sure it's something very small that I am doing incorrectly... I am receiving garbage characters from my returned value and I can't figure out why. Maybe it has to do with my encoding? Not sure.
A simple function to retrieve the value from an INI file in Windows:
LPCTSTR getConfigValue(LPCTSTR key) {
char retval[256];
DWORD dw;
if ((dw = GetPrivateProfileStringA("RLWELF", "DestinationIP", NULL, retval, 256, ".\\rlwelf.ini")) > 0) {
return NULL;
}
OutputDebugStringA(retval);
return (LPCTSTR)retval;
}
Thank you in advance!
return (LPCTSTR)retval;
You are returning the address of a local variable. That local variable is destroyed as soon as the function returns. It is therefore undefined behaviour for the caller to de-reference the returned pointer. You would need to:
Have the caller provide a buffer into which the function can write.
Have the function allocate memory on the heap. The caller would need to deallocate it.
Start using the C++ standard library and return a std::string.
Option 3 is head and shoulders above the others.
Beyond that the cast is dubious. I suspect that you are compiling with UNICODE defined. Which means that LPCTSTR expands to const wchar_t*. That in turn means that your cast would erroneous. You would be lying to the compiler. The compiler will always exact its revenge when you lie to it.
You should get out of the habit of using TCHAR. Compile with UNICODE defined and use the platform native UTF-16 character encoding for text.
Finally, GetPrivateProfileString is a really ancient API that is not encouraged to be used nowadays. The documentation says:
This function is provided only for compatibility with 16-bit Windows-based applications.
If you must use INI files, then use a good C++ library. This will result in a code writing experience that is many orders of magnitude cleaner, safer and quicker.
retval is a local variable, it is destroyed at the end of the function, so when you try to return it, the caller receives a pointer to garbage.
Instead, you could malloc a buffer and return it, take an output pointer in argument, or return a unique_ptr to a buffer.
This is a terrible idea, but i'm seeing if it's even feasible before I walk down this road.
I have to write a Win32 C++ program that can dynamically load a library based on a file that has serialized information on what dll, function, signature, and arguements to use. Loading the library is trivial (LoadLibraryEx works fine). Then getting the function pointer is easy (not a big deal, the GetProcAdderss takes care of this). However the rest is tricky.
Here's my plan of attack, feel free to let me know if this isn't the best approach:
Open the serialized information from a file on what DLL to load, and what function to execute.
LoadLibraryEx to bring in the DLL
GetProcAddress to get the function pointer (after casting the byte array to a string)
Write the arguments (which are read in as a byte array) to memory in bytes.
Get the address to the beginning of each argument (i'll know from serialization what the size of each argument is).
Using assembly jump to the beginning of the function pointer, push the addresses on the heap to the arguments in the stack (in reverse order).
Execute and get back the return value address (as a void * ?)
Use the memory address of the return value (that I got from assembly) and the size (which I got from the serialization) of the return type value and write the raw bytes back to a file.
Keep in mind my limitations:
I will never know except for run-time what the signature, dll, function name is.
It is always read in from a file.
Is there a better approach, will this approach even work?
Update
For anyone who comes poking in this thread to learn more, I found a solution. In C you can dynamically load a library using dlopen (there's a winlib of this for ease of use). Once loaded you can dynamically execute functions using libffi (supports mac/ios/win 64 and 32bit). This only gets you to C functions and primitive types (pointer,uint,int,double,float) and thats about it. However using macosx objective-c bridge you can access objective-c by loading libobjc (osx's native obj-c to c "toll free" bridge). Then through that dynamically create obj-c and c++ classes. A similar technique can be done on windows using C# and its marshaling capabilities.
This ends up with HIGH overhead, and you must be VERY careful about your memory, in addition don't mix pointers from C/C#/C++. Finally, whatever you do, at runtime. BE ABSOLUTELY SURE YOU KNOW YOUR TYPES.... seriously. BTW, libffi/cinvoke, amazing libraries.
There are existing libraries that can do what you describe, such as C/Invoke:
http://www.nongnu.org/cinvoke/
General rule, that if you have a terrible idea, drop it and find a good one.
If the signature is not known at all, what you describe will fall on face. Suppose your call works for my function as it is. I change the function from __stdcall to __cdecl or back, and you will crash.
Also you don't handle the return.
If you relax the "unknown" to allow some limitations, like fixing a return type and calling convention, you are somewhat ahead -- then really you can emulate the call but what is it good for? This whole thing sounds like a self-service hack-me engine.
The normal way is to publish some fixed interface (using function signatures), and make the DLL support it. Or arrange some uniform data transfer mechanism.
I'd suggest you to describe what you're after really and post ask that, maybe on Programmers SE.