c++ - 应用程序中奇怪的执行错误

标签 c++ debugging boost-test

我正在编写一个单元测试,它似乎存在某种指针问题。基本上,它是在测试一个类,该类一旦构建,就会返回有关文件的信息。如果检测到所有预期的文件,则测试正常运行。如果预期的文件多于检测到的文件,则例程会正确报告错误。但是,如果检测到的文件多于预期,则可执行文件会崩溃。这很难遵循,因为当我尝试使用调试器单步执行时,当前代码点会跳过整个方法——它不会像您期望的那样逐行执行。

关于我做错了什么有什么想法吗?

这是我的代码:

#include "stdafx.h"
#include "boostUnitTest.h"

#include "../pevFind/fileData.h" //Header file for tested code.
#include "../pevFind/stringUtil.h" //convertUnicode()

struct fileDataLoadingFixture
{
    std::vector<fileData> testSuiteCandidates;
    fileDataLoadingFixture()
    {
        WIN32_FIND_DATA curFileData;
        HANDLE fData = FindFirstFile(L"testFiles\\*", &curFileData);
        if (fData == INVALID_HANDLE_VALUE)
            throw std::runtime_error("Failed to load file list!");
        do {
            if(boost::algorithm::equals(curFileData.cFileName, L".")) continue;
            if(boost::algorithm::equals(curFileData.cFileName, L"..")) continue;
            fileData theFile(curFileData, L".\\testFiles\\");
            testSuiteCandidates.push_back(theFile);
        } while (FindNextFile(fData, &curFileData));
        FindClose(fData);
    };
};

BOOST_FIXTURE_TEST_SUITE( fileDataTests, fileDataLoadingFixture )

BOOST_AUTO_TEST_CASE( testPEData )
{
    std::vector<std::wstring> expectedResults;
    expectedResults.push_back(L"a.cfexe");
    expectedResults.push_back(L"b.cfexe");
    //More files.... 
    expectedResults.push_back(L"c.cfexe");
    std::sort(expectedResults.begin(), expectedResults.end());
    for (std::vector<fileData>::const_iterator it = testSuiteCandidates.begin(); it != testSuiteCandidates.end(); it++)
    {
        if (it->isPE())
        {
            std::wstring theFileString(it->getFileName().substr(it->getFileName().find_last_of(L'\\') + 1 ));
            std::vector<std::wstring>::const_iterator target = std::lower_bound(expectedResults.begin(), expectedResults.end(), theFileString);
            BOOST_REQUIRE_MESSAGE(*target == theFileString, std::string("The file ") + convertUnicode(theFileString) + " was unexpected." );
            if (*target == theFileString)
            {
                expectedResults.erase(target);
            }
        }
    }
    BOOST_CHECK_MESSAGE(expectedResults.size() == 0, "Some expected results were not found." );
}

BOOST_AUTO_TEST_SUITE_END()

谢谢!

比利3

我使用以下代码解决了这个问题:

BOOST_AUTO_TEST_CASE( testPEData )
{
    std::vector<std::wstring> expectedResults;
    expectedResults.push_back(L"blah.cfexe");
    //files
    expectedResults.push_back(L"tail.cfexe");
    expectedResults.push_back(L"zip.cfexe");
    std::vector<std::wstring> actualResults;
    for(std::vector<fileData>::const_iterator it = testSuiteCandidates.begin(); it != testSuiteCandidates.end(); it++)
    {
        if (it->isPE()) actualResults.push_back(it->getFileName().substr(it->getFileName().find_last_of(L'\\') + 1 ));
    }

    std::sort(expectedResults.begin(), expectedResults.end());
    std::sort(actualResults.begin(), actualResults.end());

    std::vector<std::wstring> missed;
    std::set_difference(expectedResults.begin(), expectedResults.end(), actualResults.begin(), actualResults.end(), std::back_inserter(missed));

    std::vector<std::wstring> incorrect;
    std::set_difference(actualResults.begin(), actualResults.end(), expectedResults.begin(), expectedResults.end(), std::back_inserter(incorrect));

    for(std::vector<std::wstring>::const_iterator it = missed.begin(); it != missed.end(); it++)
    {
        BOOST_ERROR(std::string("The file ") + convertUnicode(*it) + " was expected but not returned.");
    }

    for(std::vector<std::wstring>::const_iterator it = incorrect.begin(); it != incorrect.end(); it++)
    {
        BOOST_ERROR(std::string("The file ") + convertUnicode(*it) + " was returned but not expected.");
    }

    BOOST_CHECK(true); //Suppress commandline "No assertions" warning

}

最佳答案

如果文件是意外的,你认为这会返回什么?看起来您希望它是一个有效的文件名。

std::vector<std::wstring>::const_iterator target = std::lower_bound(expectedResults.begin(), expectedResults.end(), theFileString);

它实际上是数组末尾之后的一个迭代器——你不能把它当作一个有效的指针:

BOOST_REQUIRE_MESSAGE(*target == theFileString, std::string("The file ") + convertUnicode(theFileString) + " was unexpected." );

正常,你将结果与end()的值进行比较(固定):

BOOST_REQUIRE_MESSAGE(target != expectedResults.end() || *target == theFileString, std::string("The file ") + convertUnicode(theFileString) + " was unexpected." );
if (target != expectedResults.end() && *target == theFileString)
{
  expectedResults.erase(target);
}

参见this example here , lower_bound 将返回 off-then-end 值:

int main()
{
  int A[] = { 1, 2, 3, 3, 3, 5, 8 };
  const int N = sizeof(A) / sizeof(int);

  for (int i = 1; i <= 10; ++i) {
    int* p = lower_bound(A, A + N, i);
    cout << "Searching for " << i << ".  ";
    cout << "Result: index = " << p - A << ", ";
    if (p != A + N)
      cout << "A[" << p - A << "] == " << *p << endl;
    else
      cout << "which is off-the-end." << endl;
  }
}

The output is:

Searching for 1.  Result: index = 0, A[0] == 1
Searching for 2.  Result: index = 1, A[1] == 2
Searching for 3.  Result: index = 2, A[2] == 3
Searching for 4.  Result: index = 5, A[5] == 5
Searching for 5.  Result: index = 5, A[5] == 5
Searching for 6.  Result: index = 6, A[6] == 8
Searching for 7.  Result: index = 6, A[6] == 8
Searching for 8.  Result: index = 6, A[6] == 8
Searching for 9.  Result: index = 7, which is off-the-end.
Searching for 10.  Result: index = 7, which is off-the-end.

您不能安全地解除对尾部值的引用,但您可以将其用于比较目的或作为插入点。

你为什么要使用 lower_bound?出于搜索的目的,您肯定应该使用 find 吗?如果您使用 lower_bound,它会返回一个位置,其中可以插入文件名,但不一定等于您要查找的文件名。换句话说,您不仅需要与结束值进行比较,还需要与文件名进行比较,以防返回有效内容。

这是一个使用find 的版本。如您所见,它比上面的固定版本更简单。

std::vector<std::wstring>::const_iterator target = std::find(expectedResults.begin(), expectedResults.end(), theFileString);
BOOST_REQUIRE_MESSAGE(target != expectedResults.end(), std::string("The file ") + convertUnicode(theFileString) + " was unexpected." );
if (target != expectedResults.end())
{
  expectedResults.erase(target);
}

关于c++ - 应用程序中奇怪的执行错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1291150/

相关文章:

javascript - jQuery console.log() 在 Firefox 中不起作用

c++ - 在 Boost.Test 中抑制退出信号

c++ - 模板类中的 Int 模板成员函数

c++ - 将输入流中固定数量的元素复制到 vector 中

c++ - 我可以 #include 多个头文件吗?

python - 错误设置 django 的 ALLOWED_HOSTS 设置不会产生可理解的错误

c - gdb:线程调试不可用?

c++ - 在 Eclipse 中哪里可以找到解析的 Boost.Test 输出

C++ 单子(monad)库

c++ - 类模板部分特化的参数列表的限制中是否存在 GCC 4.9.1 (5.1) 错误?