I have been working on a few projects and needed a method similar to pythons string.split(). I decided to make a reusable piece of code and export it as a .dll, the code is below:

std::vector<std::string> Editor::StringHandler::Split(std::string data, std::string tokens)
    std::vector<std::string> returnList;
    std::string temp="";
    bool found=false;
    for (auto i : data)
    {

        found = false;
        for (auto token : tokens)
        {
            found = (i == token);
            if (found && temp.length() > 0)
            {
                returnList.push_back(temp);
                temp = "";
            }
            if (found)
            {
                break;
            }
        }

        if (!found)
        {
            temp += i;
        }

    }
    if (!found)
    {
        returnList.push_back(temp);
    }
    return returnList;
}

The code itself works fine if compiled into and executable and run; but if compiled into a dll and used in another project I get a run time error of access violation. I've tried using both returnList.reserve(data.length()); and temp.reserve(data.length()); but no avail. The call stack shows

>   msvcr110.dll!memcpy(unsigned char * dst, unsigned char * src, unsigned long count) Line 750 Unknown
    Render Engine V1.exe!wmain(int argc, wchar_t * * argv) Line 40  C++`
    Render Engine V1.exe!__tmainCRTStartup() Line 533   C`
    Render Engine V1.exe!wmainCRTStartup() Line 377 C

The code used to call the function is:

std::vector<std::string> vowels, novowels;
std::string info("test snippet of data");
std::string tokens("aeiou ");
vowels = Editor::StringHandler::Split(info);
novowels = Editor::StringHandler::Split(info, tokens);

for (auto s : vowels)
{
OutputLog(s.c_str());
}

std::cout << std::endl;

for (auto i : novowels)
{
OutputLog(i.c_str());
}

Any help as to why this is happening/how to fix it?

Recommended Answers

You need to link both the DLL and the exe to the same instance of the run-time library.

Ie. link both with the shared version of the standard library: either /MDd (Debug) or /MD (Release)

Jump to Post

I'm not sure what you mean

While building the DLL and the exe, for both use the same shared (DLL) version of the C/C++ runtime library.
http://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx

Jump to Post

All 13 Replies

Re: Code not working in DLL but working in EXE 80 80

New memory allocated in a DLL must be deallocated in the DLL. You can't allocate memory in a DLL then deallocate it in the application program because the two have different memory heaps.

Here is another thread on that topic.

Re: Code not working in DLL but working in EXE 80 80

How did you export this function from your DLL?

Re: Code not working in DLL but working in EXE 80 80

You need to link both the DLL and the exe to the same instance of the run-time library.

Ie. link both with the shared version of the standard library: either /MDd (Debug) or /MD (Release)

Re: Code not working in DLL but working in EXE 80 80

I tried adding in a pointer to a string vector, std::vector<std::string>* buffer, in the parameter and replacing returnList.push_back(temp); with buffer->push_back(temp) but I still receive the unresolved externals error.

As for how I created it, I am using MS Visual Studio 2012 Express for Desktop. I created a DLL project and made sure that DATAEDITING_EXPORTS was defined for compiling. My header file is:

#ifdef DATAEDITING_EXPORTS
#define DATAEDITING_API __declspec(dllexport)
#else
#define DATAEDITING_API __declspec(dllimport)
#endif

#include <vector>
#include <string>

namespace Editor
{
    class StringHandler
    {
    public:
        static DATAEDITING_API void Split(std::vector<std::string>* buffer, std::string data);

        static DATAEDITING_API void Split(std::vector<std::string>* buffer, std::string data, std::string tokens);
    };
}
Re: Code not working in DLL but working in EXE 80 80

You are exporting your functions the wrong way!!!

Based on your code...

The code used to call the function is:
std::vector<std::string> vowels, novowels;
std::string info("test snippet of data");
std::string tokens("aeiou ");
vowels = Editor::StringHandler::Split(info);
novowels = Editor::StringHandler::Split(info, tokens);

...the functions Editor::StringHandler::Split() and its overload is expected to return a value which type is std::vector<std::string>. You defined these functions correctly but you exported them with type void.

To correctly export these functions use this syntax: std::vector<std::string> DATAEDITING_API Split(...)

And...just a humble comment: I don't see any benefit in creating dll exports that are static members of a class. Why don't just export these functions by themselves without a class and/or namespace?

Re: Code not working in DLL but working in EXE 80 80

@ vijayan121
I'm not sure what you mean, if you mean that I need to include the lib as well as having the DLL in the executables working directory than I've done that; using #pragma comment(lib, "Editor.lib") and moving the compiled files into the lib/ref/include dirs

Re: Code not working in DLL but working in EXE 80 80

@ RonalBertogi
That was my edited header file after following Ancient Dragon's advice. As for why, I would like to create a DLL with any misc code that I find myself reusing to keep things organised and compact.

Re: Code not working in DLL but working in EXE 80 80

I'm not sure what you mean

While building the DLL and the exe, for both use the same shared (DLL) version of the C/C++ runtime library.
http://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx

Re: Code not working in DLL but working in EXE 80 80

It doesn't matter how you exported it or what lib you linked to since you can't create a vector in a dll and expect to destroy it in the application program because of heap differences. Won't work. You need another method in the DLL that will destroy the contents of the vector when no longer needed.

std::vector<std::string> Editor::StringHandler::Split(std::string data, std::string tokens)

You don't want to return a vector like that because it has to be duplicated when returned, which can be very very time consuming. Instead, pass a reference to the vector as a parameter so that Split can just modify it. Return either void or maybe bool to indicate success.

bool Editor::StringHandler::Split(std::vector<std::string> & returnList, std::string data, std::string tokens)

Re: Code not working in DLL but working in EXE 80 80

@Fearless Hornet,

I tried your code in my own project and it worked without errors. Of course, I did export your functions from my dll and called them in my exe.

However, did you try to execute your code step by step? I suggest you do this if you haven't yet and try to temporarily comment out the following lines:

for (auto s : vowels)
{
    OutputLog(s.c_str());
}
std::cout << std::endl;
for (auto i : novowels)
{
    OutputLog(i.c_str());
}
Re: Code not working in DLL but working in EXE 80 80

@vijayan121
The DLL was built with /MD and the project had /MT. Using /MD on the project initially gave errors but I was in debug mode, reverting to building both with /MDd made the program work, big thanks!

@Ancient Dragon
I already made that change since you first suggested it, thanks!

@RonalBertogi
I had the program printing each stage it went through (post-definitions, post calls to DLL, post output of data). I just thought it unnecessary to include it in the code snippet.

Thanks for the help all!

Re: Code not working in DLL but working in EXE 80 80

reverting to building both with /MDd made the program work

Building both with /MD would also work; other combinations would fail.

You don't want to return a vector like that because it has to be duplicated when returned, which can be very very time consuming

I do. Returning the vector by value is just as efficient and leads to cleaner code.
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

Re: Code not working in DLL but working in EXE 80 80

It would seem that MS Visual Studio 2012 doesn't like building a debug release with /MD, only /MDd... Either way I have 2 DLL's one for debug (/MDd) and one for release (/MD)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of 1.18 million developers, IT pros, digital marketers, and technology enthusiasts learning and sharing knowledge.