Simple C++ unit test fails with access violation

Walter 1 Reputation point
2022-02-11T19:38:45.237+00:00

I wrote a simple unit test that calls an exported function within an EXE that searches for the first space in a string. When I attempt to call it, the internal call to memchr gets an access violation. Calling _CrtCheckMemory() fails with an access violation as well.

My guess is that the CRT (C Run-Time) is not initialized in the EXE which is loaded by the unit test. I moved the function to a DLL and it works perfectly.

While I have a workaround, I'd like to understand how to get the original unit test working while testing a function from an EXE.

To repro:

  1. Create a new C++ console app from VisualStudio 2022 called AccessViolation
  2. Add a native unit test called AccessViolationTest
  3. Replace main() with

// AccessViolation.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

include <iostream>

include <string>

include <assert.h>

__declspec(dllexport) size_t TestFromExe(const std::string& test)
{
assert(_CrtCheckMemory()); // this fails
size_t index = test.find(' '); // comment previous line and this fails
return index;
}

int main()
{
std::string test = "The quick brown fox jumped over the lazy dog's back";
std::cout << "found at index " << TestFromExe(test);
}

  1. Replace unit test with

include "pch.h"

include "CppUnitTest.h"

include <string>

include <assert.h>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;
__declspec(dllimport) size_t TestFromExe(const std::string& test);

namespace AccessViolationTest
{
TEST_CLASS(AccessViolationTest)
{
public:

    TEST_METHOD(TestMethod1)
    {
        _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_CHECK_ALWAYS_DF);
        assert(_CrtCheckMemory());
        std::stringstream str;
        std::string test = "The quick brown fox jumped over the lazy dog's back";
        size_t index1 = test.find(' ');
        size_t index2 = TestFromExe(test);
        str << "index found at " << index1 << " and " << index2;
        Logger::WriteMessage(str.str().c_str());
    }
};

}

  1. Modify the properties of the unit test project to add the EXE .lib: Linker -> Input -> Additional Dependencies: $(OutDir)AccessViolation.lib
  2. Only fails from running the unit test. Console app succeeds.
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,525 questions
Visual Studio Testing
Visual Studio Testing
Visual Studio: A family of Microsoft suites of integrated development tools for building applications for Windows, the web and mobile devices.Testing: The act or process of applying tests as a means of analysis or diagnosis.
327 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Viorel 112.1K Reputation points
    2022-02-11T20:37:22.317+00:00

    According to a series of articles, exporting from EXE (using EXE as a DLL) is not a viable scenario. For example, the libraries are not initialised automatically, that is why _CrtCheckMemory and find do not work. There are some workarounds, which probably are not always reliable.

    I think that you can move your TestFromExe to a static library or a DLL that will be used by both console and tests. In simple cases you can also share some .cpp, .h or .obj files between console and tests.

    0 comments No comments