我试图为我的代码进行单位测试,而我花了很强的时间这样做。
理想的情况是,我要测试一些班级,不仅是为了发挥良好功能,而且是为了适当的记忆分配/分配。 我想知道能否利用单位测试框架进行这一检查。 我正在使用。 如果可能的话,我想看到一些样本代码!
我试图为我的代码进行单位测试,而我花了很强的时间这样做。
理想的情况是,我要测试一些班级,不仅是为了发挥良好功能,而且是为了适当的记忆分配/分配。 我想知道能否利用单位测试框架进行这一检查。 我正在使用。 如果可能的话,我想看到一些样本代码!
只要你的单位测试使用假肢时间,你就可以将假肢功能运用到灭.室进行泄漏检查。
一个简单的例子就是这样:
#include <crtdbg.h>
struct CrtCheckMemory
{
_CrtMemState state1;
_CrtMemState state2;
_CrtMemState state3;
CrtCheckMemory()
{
_CrtMemCheckpoint(&state1);
}
~CrtCheckMemory()
{
_CrtMemCheckpoint(&state2);
// using google test you can just do this.
EXPECT_EQ(0,_CrtMemDifference( &state3, &state1, &state2));
// else just do this to dump the leaked blocks to stdout.
if( _CrtMemDifference( &state3, &state1, &state2) )
_CrtMemDumpStatistics( &state3 );
}
};
在单位测试中使用:
UNIT_TEST(blah)
{
CrtCheckMemory check;
// TODO: add the unit test here
}
某些单位试验框架自行分配——例如,谷歌在单位测试失败时分配区块,因此,任何因任何其他原因而失败的试验区块也总是有虚假的“ak”。
2) 记忆泄漏探测目标:
非常清楚——探测泄漏,同时:
2.1 确切地说,确切地说,有多少按批量分配的YET没有分配。
2.2)最佳努力——如果不是确切的话,以“虚假积极”的方式表明(即使它不一定是一次泄漏,同时又是DO NOT滥用任何泄漏探测)。 对我们来说更加严厉。
2.3. 自2007年以来 我在《全球试验框架》中撰写了我的单位测试——测试每个全球试验单位试验作为“天文学实体”。
2.4 考虑使用小型/免费的“C型”拨款。
2.5 理想的做法是,考虑到C++“已到位拨款”。
2.6)易于使用并纳入现行法典(单位检测的基于测试的班级)。
2.7) 具备对每一测试和(或)整个测试类别进行“组合”主要检查环境的能力(可调/可调取的记忆检查等)。
我的解决方案利用了使用全球试验框架的继承能力,因此,它确定了我们今后将增加的每个单位试验类别的“基准”类别。 基本上,基类主要功能可分为以下几类:
3.1) 进行“第一”的G类测试,以了解在测试失败时分配到的“记忆”。 正如克里斯·贝克在上文答复的最后一句中提到的。
3.2)易于融合——简单地继承本基类,并撰写“TEST_F风格”的单位测试。
3.3.1) For each test, we can decide whether to stated otherwise perform the memory leak check or not.This is done via the SetIgnoreMemoryLeakCheckForThisTest() metohd. Note: No need to “reset” it again - it will happen automatically for the next test due to the way GTest unit tests works (they call the Ctor prior for each function call).
3.3.2) 此外,如果你事先知道你的测试将“放下”某些记忆,而且你知道这笔数额——你可以利用这两项职能,以便在进行记忆检查时考虑这一事实(通过“简单”的方式,从测试结束时使用的记忆量中减去测试开始时使用的记忆量)。
下面是头等基类:
// memoryLeakDetector.h:
#include "gtest/gtest.h"
extern int g_numOfExtraBytesAllocatedByGtestUponTestFailure;
// The fixture for testing class Foo.
class MemoryLeakDetectorBase : public ::testing::Test
{
// methods:
// -------
public:
void SetIgnoreMemoryLeakCheckForThisTest() { m_ignoreMemoryLeakCheckForThisTest= true; }
void SetIsFirstCheckRun() { m_isFirstTestRun = true; }
protected:
// You can do set-up work for each test here.
MemoryLeakDetectorBase();
// You can do clean-up work that doesn t throw exceptions here.
virtual ~MemoryLeakDetectorBase();
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following methods:
// Code here will be called immediately after the constructor (right
// before each test).
virtual void SetUp();
// Code here will be called immediately after each test (right
// before the destructor).
virtual void TearDown();
private:
void getSmartDiff(int naiveDiff);
// Add the extra memory check logic according to our
// settings for each test (this method is invoked right
// after the Dtor).
virtual void PerformMemoryCheckLogic();
// members:
// -------
private:
bool m_ignoreMemoryLeakCheckForThisTest;
bool m_isFirstTestRun;
bool m_getSmartDiff;
size_t m_numOfBytesNotToConsiderAsMemoryLeakForThisTest;
int m_firstCheck;
int m_secondCheck;
};
这里是这一基类的来源:
// memoryLeakDetectorBase.cpp
#include <iostream>
#include <malloc.h>
#include "memoryLeakDetectorBase.h"
int g_numOfExtraBytesAllocatedByGtestUponTestFailure = 0;
static int display_mallinfo_and_return_uordblks()
{
struct mallinfo mi;
mi = mallinfo();
std::cout << "========================================" << std::endl;
std::cout << "========================================" << std::endl;
std::cout << "Total non-mmapped bytes (arena):" << mi.arena << std::endl;
std::cout << "# of free chunks (ordblks):" << mi.ordblks << std::endl;
std::cout << "# of free fastbin blocks (smblks):" << mi.smblks << std::endl;
std::cout << "# of mapped regions (hblks):" << mi.hblks << std::endl;
std::cout << "Bytes in mapped regions (hblkhd):"<< mi.hblkhd << std::endl;
std::cout << "Max. total allocated space (usmblks):"<< mi.usmblks << std::endl;
std::cout << "Free bytes held in fastbins (fsmblks):"<< mi.fsmblks << std::endl;
std::cout << "Total allocated space (uordblks):"<< mi.uordblks << std::endl;
std::cout << "Total free space (fordblks):"<< mi.fordblks << std::endl;
std::cout << "Topmost releasable block (keepcost):" << mi.keepcost << std::endl;
std::cout << "========================================" << std::endl;
std::cout << "========================================" << std::endl;
std::cout << std::endl;
std::cout << std::endl;
return mi.uordblks;
}
MemoryLeakDetectorBase::MemoryLeakDetectorBase()
: m_ignoreMemoryLeakCheckForThisTest(false)
, m_isFirstTestRun(false)
, m_getSmartDiff(false)
, m_numOfBytesNotToConsiderAsMemoryLeakForThisTest(0)
{
std::cout << "MemoryLeakDetectorBase::MemoryLeakDetectorBase" << std::endl;
m_firstCheck = display_mallinfo_and_return_uordblks();
}
MemoryLeakDetectorBase::~MemoryLeakDetectorBase()
{
std::cout << "MemoryLeakDetectorBase::~MemoryLeakDetectorBase" << std::endl;
m_secondCheck = display_mallinfo_and_return_uordblks();
PerformMemoryCheckLogic();
}
void MemoryLeakDetectorBase::PerformMemoryCheckLogic()
{
if (m_isFirstTestRun) {
std::cout << "MemoryLeakDetectorBase::PerformMemoryCheckLogic - after the first test" << std::endl;
int diff = m_secondCheck - m_firstCheck;
if ( diff > 0) {
std::cout << "MemoryLeakDetectorBase::PerformMemoryCheckLogic - setting g_numOfExtraBytesAllocatedByGtestUponTestFailure to:" << diff << std::endl;
g_numOfExtraBytesAllocatedByGtestUponTestFailure = diff;
}
return;
}
if (m_ignoreMemoryLeakCheckForThisTest) {
return;
}
std::cout << "MemoryLeakDetectorBase::PerformMemoryCheckLogic" << std::endl;
int naiveDiff = m_secondCheck - m_firstCheck;
// in case you wish for "more accurate" difference calculation call this method
if (m_getSmartDiff) {
getSmartDiff(naiveDiff);
}
EXPECT_EQ(m_firstCheck,m_secondCheck);
std::cout << "MemoryLeakDetectorBase::PerformMemoryCheckLogic - the difference is:" << naiveDiff << std::endl;
}
void MemoryLeakDetectorBase::getSmartDiff(int naiveDiff)
{
// according to some invastigations and assumemptions, it seems like once there is at least one
// allocation which is not handled - GTest allocates 32 bytes on the heap, so in case the difference
// prior for any further substrcutions is less than 32 - we will assume that the test does not need to
// go over memory leak check...
std::cout << "MemoryLeakDetectorBase::getMoreAccurateAmountOfBytesToSubstructFromSecondMemoryCheck - start" << std::endl;
if (naiveDiff <= 32) {
std::cout << "MemoryLeakDetectorBase::getSmartDiff - the naive diff <= 32 - ignoring..." << std::endl;
return;
}
size_t numOfBytesToReduceFromTheSecondMemoryCheck = m_numOfBytesNotToConsiderAsMemoryLeakForThisTest + g_numOfExtraBytesAllocatedByGtestUponTestFailure;
m_secondCheck -= numOfBytesToReduceFromTheSecondMemoryCheck;
std::cout << "MemoryLeakDetectorBase::getSmartDiff - substructing " << numOfBytesToReduceFromTheSecondMemoryCheck << std::endl;
}
void MemoryLeakDetectorBase::SetUp()
{
std::cout << "MemoryLeakDetectorBase::SetUp" << std::endl;
}
void MemoryLeakDetectorBase::TearDown()
{
std::cout << "MemoryLeakDetectorBase::TearDown" << std::endl;
}
// The actual test of this module:
TEST_F(MemoryLeakDetectorBase, getNumOfExtraBytesGTestAllocatesUponTestFailureTest)
{
std::cout << "MemoryLeakDetectorPocTest::getNumOfExtraBytesGTestAllocatesUponTestFailureTest - START" << std::endl;
// Allocate some bytes on the heap and DO NOT delete them so we can find out the amount
// of extra bytes GTest framework allocates upon a failure of a test.
// This way, upon our legit test failure, we will be able to determine of many bytes were NOT
// deleted EXACTLY by our test.
std::cout << "MemoryLeakDetectorPocTest::getNumOfExtraBytesGTestAllocatesUponTestFailureTest - size of char:" << sizeof(char) << std::endl;
char* pChar = new char( g );
SetIsFirstCheckRun();
std::cout << "MemoryLeakDetectorPocTest::getNumOfExtraBytesGTestAllocatesUponTestFailureTest - END" << std::endl;
}
最后,如果我们能够(或不)发现错失的解职地点,则使用这一基类的样本“基于试验的”单位测试类别,并表明使用和若干不同的POC(概念不受影响)。
// memoryLeakDetectorPocTest.cpp
#include "memoryLeakDetectorPocTest.h"
#include <cstdlib> // for malloc
class MyObject
{
public:
MyObject(int a, int b) : m_a(a), m_b(b) { std::cout << "MyObject::MyObject" << std::endl; }
~MyObject() { std::cout << "MyObject::~MyObject" << std::endl; }
private:
int m_a;
int m_b;
};
MemoryLeakDetectorPocTest::MemoryLeakDetectorPocTest()
{
std::cout << "MemoryLeakDetectorPocTest::MemoryLeakDetectorPocTest" << std::endl;
}
MemoryLeakDetectorPocTest::~MemoryLeakDetectorPocTest()
{
std::cout << "MemoryLeakDetectorPocTest::~MemoryLeakDetectorPocTest" << std::endl;
}
void MemoryLeakDetectorPocTest::SetUp()
{
std::cout << "MemoryLeakDetectorPocTest::SetUp" << std::endl;
}
void MemoryLeakDetectorPocTest::TearDown()
{
std::cout << "MemoryLeakDetectorPocTest::TearDown" << std::endl;
}
TEST_F(MemoryLeakDetectorPocTest, verifyNewAllocationForNativeType)
{
std::cout << "MemoryLeakDetectorPocTest::verifyNewAllocationForNativeType - START" << std::endl;
// allocate some bytes on the heap and intentially DONT release them...
const size_t numOfCharsOnHeap = 23;
std::cout << "size of char is:" << sizeof(char) << " bytes" << std::endl;
std::cout << "allocating " << sizeof(char) * numOfCharsOnHeap << " bytes on the heap using new []" << std::endl;
char* arr = new char[numOfCharsOnHeap];
// DO NOT delete it on purpose...
//delete [] arr;
std::cout << "MemoryLeakDetectorPocTest::verifyNewAllocationForNativeType - END" << std::endl;
}
TEST_F(MemoryLeakDetectorPocTest, verifyNewAllocationForUserDefinedType)
{
std::cout << "MemoryLeakDetectorPocTest::verifyNewAllocationForUserDefinedType - START" << std::endl;
std::cout << "size of MyObject is:" << sizeof(MyObject) << " bytes" << std::endl;
std::cout << "allocating MyObject on the heap using new" << std::endl;
MyObject* myObj1 = new MyObject(12, 17);
delete myObj1;
std::cout << "MemoryLeakDetectorPocTest::verifyNewAllocationForUserDefinedType - END" << std::endl;
}
TEST_F(MemoryLeakDetectorPocTest, verifyMallocAllocationForNativeType)
{
std::cout << "MemoryLeakDetectorPocTest::verifyMallocAllocationForNativeType - START" << std::endl;
size_t numOfDoublesOnTheHeap = 3;
std::cout << "MemoryLeakDetectorPocTest::verifyMallocAllocationForNativeType - sizeof double is " << sizeof(double) << std::endl;
std::cout << "MemoryLeakDetectorPocTest::verifyMallocAllocationForNativeType - allocaitng " << sizeof(double) * numOfDoublesOnTheHeap << " bytes on the heap" << std::endl;
double* arr = static_cast<double*>(malloc(sizeof(double) * numOfDoublesOnTheHeap));
// NOT free-ing them on purpose !!
// free(arr);
std::cout << "MemoryLeakDetectorPocTest::verifyMallocAllocationForNativeType - END" << std::endl;
}
TEST_F(MemoryLeakDetectorPocTest, verifyNewAllocationForNativeSTLVectorType)
{
std::cout << "MemoryLeakDetectorPocTest::verifyNewAllocationForNativeSTLVectorType - START" << std::endl;
std::vector<int> vecInt;
vecInt.push_back(12);
vecInt.push_back(15);
vecInt.push_back(17);
std::cout << "MemoryLeakDetectorPocTest::verifyNewAllocationForNativeSTLVectorType - END" << std::endl;
}
TEST_F(MemoryLeakDetectorPocTest, verifyNewAllocationForUserDefinedSTLVectorType)
{
std::cout << "MemoryLeakDetectorPocTest::verifyNewAllocationForUserDefinedSTLVectorType - START" << std::endl;
std::vector<MyObject*> vecMyObj;
vecMyObj.push_back(new MyObject(7,8));
vecMyObj.push_back(new MyObject(9,10));
size_t vecSize = vecMyObj.size();
for (int i = 0; i < vecSize; ++i) {
delete vecMyObj[i];
}
std::cout << "MemoryLeakDetectorPocTest::verifyNewAllocationForUserDefinedSTLVectorType - END" << std::endl;
}
TEST_F(MemoryLeakDetectorPocTest, verifyInPlaceAllocationAndDeAllocationForUserDefinedType)
{
std::cout << "MemoryLeakDetectorPocTest::verifyInPlaceAllocationAndDeAllocationForUserDefinedType - START" << std::endl;
void* p1 = malloc(sizeof(MyObject));
MyObject *p2 = new (p1) MyObject(12,13);
p2->~MyObject();
std::cout << "MemoryLeakDetectorPocTest::verifyInPlaceAllocationAndDeAllocationForUserDefinedType - END" << std::endl;
}
TEST_F(MemoryLeakDetectorPocTest, verifyInPlaceAllocationForUserDefinedType)
{
std::cout << "MemoryLeakDetectorPocTest::verifyInPlaceAllocationForUserDefinedType - START" << std::endl;
void* p1 = malloc(sizeof(MyObject));
MyObject *p2 = new (p1) MyObject(12,13);
// Dont delete the object on purpose !!
//p2->~MyObject();
std::cout << "MemoryLeakDetectorPocTest::verifyInPlaceAllocationForUserDefinedType - END" << std::endl;
}
该类别的负责人档案:
// memoryLeakDetectorPocTest.h
#include "gtest/gtest.h"
#include "memoryLeakDetectorBase.h"
// The fixture for testing class Foo.
class MemoryLeakDetectorPocTest : public MemoryLeakDetectorBase
{
protected:
// You can do set-up work for each test here.
MemoryLeakDetectorPocTest();
// You can do clean-up work that doesn t throw exceptions here.
virtual ~MemoryLeakDetectorPocTest();
// Code here will be called immediately after the constructor (right
// before each test).
virtual void SetUp();
// Code here will be called immediately after each test (right
// before the destructor).
virtual void TearDown();
};
您可以通过提供自己的执行<代码>new、delete
、 Smalloc
和free
的功能,通过增加有关分配的记忆跟踪信息,来发现测试中的记忆泄露。
I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...
I have been searching for sample code creating iterator for my own container, but I haven t really found a good example. I know this been asked before (Creating my own Iterators) but didn t see any ...
Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...
I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?
Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...
Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...
I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...
Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?