mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-17 21:48:19 +00:00
Type safe mem_zero function (fixes #5228)
Partially replaces #5690. POD types are just memset. Other types are either destructed if not trivial and/or constructed if not trivial. Types need to have a default constructor. Virtual classes can be mem_zeroed only if they already have been constructed, otherwise it is UB.
This commit is contained in:
parent
ee04cd4dda
commit
6e629e1deb
|
@ -325,6 +325,8 @@ if(NOT MSVC AND NOT HAIKU)
|
||||||
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wthread-safety)
|
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wthread-safety)
|
||||||
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wthread-safety-negative)
|
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wthread-safety-negative)
|
||||||
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wsuggest-override)
|
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wsuggest-override)
|
||||||
|
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wdynamic-class-memaccess) # clang
|
||||||
|
add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wclass-memaccess) # gcc
|
||||||
add_linker_flag_if_supported(OUR_FLAGS_LINK -Wno-alloc-size-larger-than) # save.cpp with LTO
|
add_linker_flag_if_supported(OUR_FLAGS_LINK -Wno-alloc-size-larger-than) # save.cpp with LTO
|
||||||
# add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wdouble-promotion) # Many occurrences
|
# add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wdouble-promotion) # Many occurrences
|
||||||
# add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wnull-dereference) # Many occurrences
|
# add_cxx_compiler_flag_if_supported(OUR_FLAGS_OWN -Wnull-dereference) # Many occurrences
|
||||||
|
@ -2750,6 +2752,7 @@ if(GTEST_FOUND OR DOWNLOAD_GTEST)
|
||||||
linereader.cpp
|
linereader.cpp
|
||||||
mapbugs.cpp
|
mapbugs.cpp
|
||||||
math.cpp
|
math.cpp
|
||||||
|
memory.cpp
|
||||||
name_ban.cpp
|
name_ban.cpp
|
||||||
net.cpp
|
net.cpp
|
||||||
netaddr.cpp
|
netaddr.cpp
|
||||||
|
|
|
@ -236,11 +236,6 @@ void mem_move(void *dest, const void *source, size_t size)
|
||||||
memmove(dest, source, size);
|
memmove(dest, source, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_zero(void *block, size_t size)
|
|
||||||
{
|
|
||||||
memset(block, 0, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mem_comp(const void *a, const void *b, size_t size)
|
int mem_comp(const void *a, const void *b, size_t size)
|
||||||
{
|
{
|
||||||
return memcmp(a, b, size);
|
return memcmp(a, b, size);
|
||||||
|
|
|
@ -171,7 +171,55 @@ void mem_move(void *dest, const void *source, size_t size);
|
||||||
* @param block Pointer to the block to zero out.
|
* @param block Pointer to the block to zero out.
|
||||||
* @param size Size of the block.
|
* @param size Size of the block.
|
||||||
*/
|
*/
|
||||||
void mem_zero(void *block, size_t size);
|
template<typename T>
|
||||||
|
inline void mem_zero(T *block, size_t size)
|
||||||
|
{
|
||||||
|
typedef typename std::remove_all_extents<T>::type BaseT;
|
||||||
|
if constexpr(std::is_pointer<T>::value || std::is_pointer<BaseT>::value)
|
||||||
|
{
|
||||||
|
// pointer of pointer, just memset it
|
||||||
|
memset(block, 0, size);
|
||||||
|
}
|
||||||
|
else if constexpr(std::is_array<T>::value)
|
||||||
|
{ // pointer to array type
|
||||||
|
if constexpr(std::is_fundamental<BaseT>::value)
|
||||||
|
{ // array of fundamental type, just memset it
|
||||||
|
memset(block, 0, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // array of user defined type, destroying all objects and recreating new ones
|
||||||
|
const size_t N = size / sizeof(BaseT);
|
||||||
|
if constexpr(!std::is_trivially_destructible<BaseT>::value)
|
||||||
|
{ // non trivial destructor means user provided or virtual destructor, see https://en.cppreference.com/w/cpp/language/destructor#Trivial_destructor
|
||||||
|
// so we gotta call it manually
|
||||||
|
for(size_t i(0); i < N; ++i)
|
||||||
|
((BaseT *)block)[i].~BaseT();
|
||||||
|
}
|
||||||
|
if constexpr(std::is_trivially_constructible<BaseT>::value)
|
||||||
|
memset(block, 0, size); // trivial constructor implies POD
|
||||||
|
else
|
||||||
|
new(block) BaseT[N]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if constexpr(std::is_fundamental<typename std::remove_pointer<T>::type>::value || std::is_same<decltype(block), void *>::value)
|
||||||
|
{ // pointer to fundamental type, just memset it
|
||||||
|
memset(block, 0, size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // pointer to type T, BUT CAN BE AN ARRAY...
|
||||||
|
const size_t N = size / sizeof(T);
|
||||||
|
if constexpr(!std::is_trivially_destructible<T>::value)
|
||||||
|
{ // non trivial destructor means user provided or virtual destructor, see https://en.cppreference.com/w/cpp/language/destructor#Trivial_destructor
|
||||||
|
// so we gotta call it manually
|
||||||
|
for(size_t i(0); i < N; ++i)
|
||||||
|
block[i].~T();
|
||||||
|
}
|
||||||
|
if constexpr(std::is_trivially_constructible<T>::value)
|
||||||
|
memset(block, 0, size); // trivial constructor implies POD
|
||||||
|
else
|
||||||
|
new(block) T[N]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares two blocks of memory
|
* Compares two blocks of memory
|
||||||
|
|
|
@ -4195,9 +4195,7 @@ void CClient::RegisterCommands()
|
||||||
|
|
||||||
static CClient *CreateClient()
|
static CClient *CreateClient()
|
||||||
{
|
{
|
||||||
CClient *pClient = static_cast<CClient *>(malloc(sizeof(*pClient)));
|
return new CClient;
|
||||||
mem_zero(pClient, sizeof(CClient));
|
|
||||||
return new(pClient) CClient;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::HandleConnectAddress(const NETADDR *pAddr)
|
void CClient::HandleConnectAddress(const NETADDR *pAddr)
|
||||||
|
@ -4369,8 +4367,7 @@ int main(int argc, const char **argv)
|
||||||
CleanerFunctions.emplace([pKernel, pClient]() {
|
CleanerFunctions.emplace([pKernel, pClient]() {
|
||||||
pKernel->Shutdown();
|
pKernel->Shutdown();
|
||||||
delete pKernel;
|
delete pKernel;
|
||||||
pClient->~CClient();
|
delete pClient;
|
||||||
free(pClient);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const std::thread::id MainThreadId = std::this_thread::get_id();
|
const std::thread::id MainThreadId = std::this_thread::get_id();
|
||||||
|
|
389
src/test/memory.cpp
Normal file
389
src/test/memory.cpp
Normal file
|
@ -0,0 +1,389 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <base/system.h>
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
static std::mt19937 gs_randomizer;
|
||||||
|
|
||||||
|
void mem_fill(void *block, size_t size)
|
||||||
|
{
|
||||||
|
unsigned char *bytes = (unsigned char *)block;
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
bytes[i] = gs_randomizer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mem_is_null(const void *block, size_t size)
|
||||||
|
{
|
||||||
|
const unsigned char *bytes = (const unsigned char *)block;
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
if(bytes[i] != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Memory, BaseTypes)
|
||||||
|
{
|
||||||
|
void *aVoid[123];
|
||||||
|
mem_fill(aVoid, sizeof(aVoid));
|
||||||
|
EXPECT_FALSE(mem_is_null(aVoid, sizeof(aVoid)));
|
||||||
|
mem_zero(&aVoid, sizeof(aVoid));
|
||||||
|
EXPECT_TRUE(mem_is_null(aVoid, sizeof(aVoid)));
|
||||||
|
mem_fill(aVoid, sizeof(aVoid));
|
||||||
|
EXPECT_FALSE(mem_is_null(aVoid, sizeof(aVoid)));
|
||||||
|
mem_zero(&aVoid[0], 123 * sizeof(void *));
|
||||||
|
EXPECT_TRUE(mem_is_null(aVoid, sizeof(aVoid)));
|
||||||
|
|
||||||
|
mem_fill(aVoid, sizeof(aVoid));
|
||||||
|
EXPECT_FALSE(mem_is_null(aVoid, sizeof(aVoid)));
|
||||||
|
mem_zero(aVoid, sizeof(aVoid));
|
||||||
|
EXPECT_TRUE(mem_is_null(aVoid, sizeof(aVoid)));
|
||||||
|
|
||||||
|
int aInt[512];
|
||||||
|
mem_fill(aInt, sizeof(aInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aInt, sizeof(aInt)));
|
||||||
|
mem_zero(&aInt, sizeof(aInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aInt, sizeof(aInt)));
|
||||||
|
mem_fill(aInt, sizeof(aInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aInt, sizeof(aInt)));
|
||||||
|
mem_zero(&aInt[0], sizeof(aInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aInt, sizeof(aInt)));
|
||||||
|
|
||||||
|
mem_fill(aInt, sizeof(aInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aInt, sizeof(aInt)));
|
||||||
|
mem_zero(aInt, sizeof(aInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aInt, sizeof(aInt)));
|
||||||
|
|
||||||
|
int *apInt[512];
|
||||||
|
mem_fill(apInt, sizeof(apInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(apInt, sizeof(apInt)));
|
||||||
|
mem_zero(&apInt, sizeof(apInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(apInt, sizeof(apInt)));
|
||||||
|
|
||||||
|
mem_fill(apInt, sizeof(apInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(apInt, sizeof(apInt)));
|
||||||
|
mem_zero(apInt, sizeof(apInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(apInt, sizeof(apInt)));
|
||||||
|
|
||||||
|
int aaInt[10][20];
|
||||||
|
mem_fill(aaInt, sizeof(aaInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aaInt, sizeof(aaInt)));
|
||||||
|
mem_zero(&aaInt, sizeof(aaInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aaInt, sizeof(aaInt)));
|
||||||
|
mem_fill(aaInt, sizeof(aaInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aaInt, sizeof(aaInt)));
|
||||||
|
mem_zero(&aaInt[0], sizeof(aaInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aaInt, sizeof(aaInt)));
|
||||||
|
mem_fill(aaInt, sizeof(aaInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aaInt, sizeof(aaInt)));
|
||||||
|
mem_zero(&aaInt[0][0], sizeof(aaInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aaInt, sizeof(aaInt)));
|
||||||
|
|
||||||
|
mem_fill(aaInt, sizeof(aaInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aaInt, sizeof(aaInt)));
|
||||||
|
mem_zero(aaInt, sizeof(aaInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aaInt, sizeof(aaInt)));
|
||||||
|
mem_fill(aaInt, sizeof(aaInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aaInt, sizeof(aaInt)));
|
||||||
|
mem_zero(aaInt[0], sizeof(aaInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aaInt, sizeof(aaInt)));
|
||||||
|
|
||||||
|
int *aapInt[10][20];
|
||||||
|
mem_fill(aapInt, sizeof(aapInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aapInt, sizeof(aapInt)));
|
||||||
|
mem_zero(&aapInt, sizeof(aapInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aapInt, sizeof(aapInt)));
|
||||||
|
mem_fill(aapInt, sizeof(aapInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aapInt, sizeof(aapInt)));
|
||||||
|
mem_zero(&aapInt[0], sizeof(aapInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aapInt, sizeof(aapInt)));
|
||||||
|
|
||||||
|
mem_fill(aapInt, sizeof(aapInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aapInt, sizeof(aapInt)));
|
||||||
|
mem_zero(aapInt, sizeof(aapInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aapInt, sizeof(aapInt)));
|
||||||
|
mem_fill(aapInt, sizeof(aapInt));
|
||||||
|
EXPECT_FALSE(mem_is_null(aapInt, sizeof(aapInt)));
|
||||||
|
mem_zero(aapInt[0], sizeof(aapInt));
|
||||||
|
EXPECT_TRUE(mem_is_null(aapInt, sizeof(aapInt)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Memory, PODTypes)
|
||||||
|
{
|
||||||
|
NETADDR aAddr[123];
|
||||||
|
mem_fill(aAddr, sizeof(aAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(aAddr, sizeof(aAddr)));
|
||||||
|
mem_zero(&aAddr, sizeof(aAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(aAddr, sizeof(aAddr)));
|
||||||
|
mem_fill(aAddr, sizeof(aAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(aAddr, sizeof(aAddr)));
|
||||||
|
mem_zero(&aAddr[0], sizeof(aAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(aAddr, sizeof(aAddr)));
|
||||||
|
|
||||||
|
mem_fill(aAddr, sizeof(aAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(aAddr, sizeof(aAddr)));
|
||||||
|
mem_zero(aAddr, sizeof(aAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(aAddr, sizeof(aAddr)));
|
||||||
|
|
||||||
|
NETADDR *apAddr[123];
|
||||||
|
mem_fill(apAddr, sizeof(apAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(apAddr, sizeof(apAddr)));
|
||||||
|
mem_zero((NETADDR **)apAddr, sizeof(apAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(apAddr, sizeof(apAddr)));
|
||||||
|
mem_fill(apAddr, sizeof(apAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(apAddr, sizeof(apAddr)));
|
||||||
|
mem_zero(&apAddr, sizeof(apAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(apAddr, sizeof(apAddr)));
|
||||||
|
mem_fill(apAddr, sizeof(apAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(apAddr, sizeof(apAddr)));
|
||||||
|
mem_zero(&apAddr[0], sizeof(apAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(apAddr, sizeof(apAddr)));
|
||||||
|
mem_fill(apAddr, sizeof(apAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(apAddr, sizeof(apAddr)));
|
||||||
|
mem_zero(apAddr, sizeof(apAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(apAddr, sizeof(apAddr)));
|
||||||
|
|
||||||
|
// 2D arrays
|
||||||
|
NETADDR aaAddr[10][20];
|
||||||
|
mem_fill(aaAddr, sizeof(aaAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null((NETADDR *)aaAddr, sizeof(aaAddr)));
|
||||||
|
mem_zero(&aaAddr, sizeof(aaAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null((NETADDR *)aaAddr, sizeof(aaAddr)));
|
||||||
|
mem_fill(aaAddr, sizeof(aaAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null((NETADDR *)aaAddr, sizeof(aaAddr)));
|
||||||
|
mem_zero(&aaAddr[0], sizeof(aaAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null((NETADDR *)aaAddr, sizeof(aaAddr)));
|
||||||
|
mem_fill(aaAddr, sizeof(aaAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null((NETADDR *)aaAddr, sizeof(aaAddr)));
|
||||||
|
mem_zero(&aaAddr[0][0], sizeof(aaAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null((NETADDR *)aaAddr, sizeof(aaAddr)));
|
||||||
|
|
||||||
|
mem_fill(aaAddr, sizeof(aaAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null((NETADDR *)aaAddr, sizeof(aaAddr)));
|
||||||
|
mem_zero(aaAddr, sizeof(aaAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null((NETADDR *)aaAddr, sizeof(aaAddr)));
|
||||||
|
mem_fill(aaAddr, sizeof(aaAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null((NETADDR *)aaAddr, sizeof(aaAddr)));
|
||||||
|
mem_zero(aaAddr[0], sizeof(aaAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null((NETADDR *)aaAddr, sizeof(aaAddr)));
|
||||||
|
|
||||||
|
// 2D pointer arrays
|
||||||
|
NETADDR *aapAddr[10][20];
|
||||||
|
mem_fill(aapAddr, sizeof(aapAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(aapAddr, sizeof(aapAddr)));
|
||||||
|
mem_zero(&aapAddr, sizeof(aapAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(aapAddr, sizeof(aapAddr)));
|
||||||
|
mem_fill(aapAddr, sizeof(aapAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(aapAddr, sizeof(aapAddr)));
|
||||||
|
mem_zero(&aapAddr[0], sizeof(aapAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(aapAddr, sizeof(aapAddr)));
|
||||||
|
mem_fill(aapAddr, sizeof(aapAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(aapAddr, sizeof(aapAddr)));
|
||||||
|
mem_zero(&aapAddr[0][0], sizeof(aapAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(aapAddr, sizeof(aapAddr)));
|
||||||
|
|
||||||
|
mem_fill(aapAddr, sizeof(aapAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(aapAddr, sizeof(aapAddr)));
|
||||||
|
mem_zero(aapAddr, sizeof(aapAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(aapAddr, sizeof(aapAddr)));
|
||||||
|
mem_fill(aapAddr, sizeof(aapAddr));
|
||||||
|
EXPECT_FALSE(mem_is_null(aapAddr, sizeof(aapAddr)));
|
||||||
|
mem_zero(aapAddr[0], sizeof(aapAddr));
|
||||||
|
EXPECT_TRUE(mem_is_null(aapAddr, sizeof(aapAddr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CDummyClass
|
||||||
|
{
|
||||||
|
int x = 1234;
|
||||||
|
int y;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool mem_is_null(CDummyClass *block, size_t size)
|
||||||
|
{
|
||||||
|
const CDummyClass *data = block;
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < size / sizeof(CDummyClass); i++)
|
||||||
|
{
|
||||||
|
if(data[i].x != 1234 || data[i].y != 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Memory, ConstructibleTypes)
|
||||||
|
{
|
||||||
|
CDummyClass aTest[123];
|
||||||
|
mem_fill(aTest, sizeof(aTest));
|
||||||
|
EXPECT_FALSE(mem_is_null(aTest, sizeof(aTest)));
|
||||||
|
mem_zero(&aTest, sizeof(aTest));
|
||||||
|
EXPECT_TRUE(mem_is_null(aTest, sizeof(aTest)));
|
||||||
|
mem_fill(aTest, sizeof(aTest));
|
||||||
|
EXPECT_FALSE(mem_is_null(aTest, sizeof(aTest)));
|
||||||
|
mem_zero(&aTest[0], sizeof(aTest));
|
||||||
|
EXPECT_TRUE(mem_is_null(aTest, sizeof(aTest)));
|
||||||
|
|
||||||
|
mem_fill(aTest, sizeof(aTest));
|
||||||
|
EXPECT_FALSE(mem_is_null(aTest, sizeof(aTest)));
|
||||||
|
mem_zero(aTest, sizeof(aTest));
|
||||||
|
EXPECT_TRUE(mem_is_null(aTest, sizeof(aTest)));
|
||||||
|
|
||||||
|
CDummyClass aaTest[2][2];
|
||||||
|
mem_fill(aaTest, sizeof(aaTest));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass *)aaTest, sizeof(aaTest)));
|
||||||
|
mem_zero(&aaTest, sizeof(aaTest));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass *)aaTest, sizeof(aaTest)));
|
||||||
|
mem_fill(aaTest, sizeof(aaTest));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass *)aaTest, sizeof(aaTest)));
|
||||||
|
mem_zero(&aaTest[0], sizeof(aaTest));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass *)aaTest, sizeof(aaTest)));
|
||||||
|
mem_fill(aaTest, sizeof(aaTest));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass *)aaTest, sizeof(aaTest)));
|
||||||
|
mem_zero(&aaTest[0][0], sizeof(aaTest));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass *)aaTest, sizeof(aaTest)));
|
||||||
|
|
||||||
|
mem_fill(aaTest, sizeof(aaTest));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass *)aaTest, sizeof(aaTest)));
|
||||||
|
mem_zero(aaTest, sizeof(aaTest));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass *)aaTest, sizeof(aaTest)));
|
||||||
|
mem_fill(aaTest, sizeof(aaTest));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass *)aaTest, sizeof(aaTest)));
|
||||||
|
mem_zero(aaTest[0], sizeof(aaTest));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass *)aaTest, sizeof(aaTest)));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CDummyClass2
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
~CDummyClass2()
|
||||||
|
{
|
||||||
|
if(x == 684684 && y == -12345678)
|
||||||
|
dbg_break();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(Memory, DestructibleTypes)
|
||||||
|
{
|
||||||
|
CDummyClass2 aTest2[123];
|
||||||
|
mem_fill(aTest2, sizeof(aTest2));
|
||||||
|
EXPECT_FALSE(mem_is_null(aTest2, sizeof(aTest2)));
|
||||||
|
mem_zero(&aTest2, sizeof(aTest2));
|
||||||
|
EXPECT_TRUE(mem_is_null(aTest2, sizeof(aTest2)));
|
||||||
|
mem_fill(aTest2, sizeof(aTest2));
|
||||||
|
EXPECT_FALSE(mem_is_null(aTest2, sizeof(aTest2)));
|
||||||
|
mem_zero(&aTest2[0], sizeof(aTest2));
|
||||||
|
EXPECT_TRUE(mem_is_null(aTest2, sizeof(aTest2)));
|
||||||
|
|
||||||
|
mem_fill(aTest2, sizeof(aTest2));
|
||||||
|
EXPECT_FALSE(mem_is_null(aTest2, sizeof(aTest2)));
|
||||||
|
mem_zero(aTest2, sizeof(aTest2));
|
||||||
|
EXPECT_TRUE(mem_is_null(aTest2, sizeof(aTest2)));
|
||||||
|
|
||||||
|
CDummyClass2 aaTest2[10][20];
|
||||||
|
mem_fill(aaTest2, sizeof(aaTest2));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass2 *)aaTest2, sizeof(aaTest2)));
|
||||||
|
mem_zero(&aaTest2, sizeof(aaTest2));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass2 *)aaTest2, sizeof(aaTest2)));
|
||||||
|
mem_fill(aaTest2, sizeof(aaTest2));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass2 *)aaTest2, sizeof(aaTest2)));
|
||||||
|
mem_zero(&aaTest2[0], sizeof(aaTest2));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass2 *)aaTest2, sizeof(aaTest2)));
|
||||||
|
mem_fill(aaTest2, sizeof(aaTest2));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass2 *)aaTest2, sizeof(aaTest2)));
|
||||||
|
mem_zero(&aaTest2[0][0], sizeof(aaTest2));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass2 *)aaTest2, sizeof(aaTest2)));
|
||||||
|
|
||||||
|
mem_fill(aaTest2, sizeof(aaTest2));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass2 *)aaTest2, sizeof(aaTest2)));
|
||||||
|
mem_zero(aaTest2, sizeof(aaTest2));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass2 *)aaTest2, sizeof(aaTest2)));
|
||||||
|
|
||||||
|
mem_fill(aaTest2, sizeof(aaTest2));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass2 *)aaTest2, sizeof(aaTest2)));
|
||||||
|
mem_zero(aaTest2[0], sizeof(aaTest2));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass2 *)aaTest2, sizeof(aaTest2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CDummyClass3
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
std::vector<int> v;
|
||||||
|
};
|
||||||
|
|
||||||
|
void mem_fill(CDummyClass3 *block, size_t size)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < size / sizeof(CDummyClass3); i++)
|
||||||
|
{
|
||||||
|
block[i].x = gs_randomizer();
|
||||||
|
block[i].y = gs_randomizer();
|
||||||
|
block[i].v.resize(gs_randomizer() & 127, gs_randomizer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mem_is_null(CDummyClass3 *block, size_t size)
|
||||||
|
{
|
||||||
|
const CDummyClass3 *data = block;
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < size / sizeof(CDummyClass3); i++)
|
||||||
|
{
|
||||||
|
if(data[i].x != 0 || data[i].y != 0 || !data[i].v.empty())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Memory, ComplexTypes)
|
||||||
|
{
|
||||||
|
CDummyClass3 aTest3[123];
|
||||||
|
mem_fill(aTest3, sizeof(aTest3));
|
||||||
|
EXPECT_FALSE(mem_is_null(aTest3, sizeof(aTest3)));
|
||||||
|
mem_zero(&aTest3, sizeof(aTest3));
|
||||||
|
EXPECT_TRUE(mem_is_null(aTest3, sizeof(aTest3)));
|
||||||
|
mem_fill(aTest3, sizeof(aTest3));
|
||||||
|
EXPECT_FALSE(mem_is_null(aTest3, sizeof(aTest3)));
|
||||||
|
mem_zero(&aTest3[0], sizeof(aTest3));
|
||||||
|
EXPECT_TRUE(mem_is_null(aTest3, sizeof(aTest3)));
|
||||||
|
|
||||||
|
mem_fill(aTest3, sizeof(aTest3));
|
||||||
|
EXPECT_FALSE(mem_is_null(aTest3, sizeof(aTest3)));
|
||||||
|
mem_zero(aTest3, sizeof(aTest3));
|
||||||
|
EXPECT_TRUE(mem_is_null(aTest3, sizeof(aTest3)));
|
||||||
|
|
||||||
|
CDummyClass3 aaTest3[10][20];
|
||||||
|
mem_fill((CDummyClass3 *)aaTest3, sizeof(aaTest3));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass3 *)aaTest3, sizeof(aaTest3)));
|
||||||
|
mem_zero(&aaTest3, sizeof(aaTest3));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass3 *)aaTest3, sizeof(aaTest3)));
|
||||||
|
mem_fill((CDummyClass3 *)aaTest3, sizeof(aaTest3));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass3 *)aaTest3, sizeof(aaTest3)));
|
||||||
|
mem_zero(&aaTest3[0], sizeof(aaTest3));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass3 *)aaTest3, sizeof(aaTest3)));
|
||||||
|
mem_fill((CDummyClass3 *)aaTest3, sizeof(aaTest3));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass3 *)aaTest3, sizeof(aaTest3)));
|
||||||
|
mem_zero(&aaTest3[0][0], sizeof(aaTest3));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass3 *)aaTest3, sizeof(aaTest3)));
|
||||||
|
|
||||||
|
mem_fill((CDummyClass3 *)aaTest3, sizeof(aaTest3));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass3 *)aaTest3, sizeof(aaTest3)));
|
||||||
|
mem_zero(aaTest3, sizeof(aaTest3));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass3 *)aaTest3, sizeof(aaTest3)));
|
||||||
|
mem_fill((CDummyClass3 *)aaTest3, sizeof(aaTest3));
|
||||||
|
EXPECT_FALSE(mem_is_null((CDummyClass3 *)aaTest3, sizeof(aaTest3)));
|
||||||
|
mem_zero(aaTest3[0], sizeof(aaTest3));
|
||||||
|
EXPECT_TRUE(mem_is_null((CDummyClass3 *)aaTest3, sizeof(aaTest3)));
|
||||||
|
}
|
Loading…
Reference in a new issue