क्या आप मुझे समझने में मदद कर सकते हैं कि जीटीएस्ट और स्ट्रक्चर पैकिंग के साथ क्या हो रहा है?सी ++ - structs के साथ जीटीएस्ट वैल्यू-पैरामीटरयुक्त परीक्षणों का उपयोग करते हुए वाल्ग्रिंड त्रुटियों का कारण बनता है
समस्या यह है कि जीटीएस्ट में मान-पैरामीटर परीक्षण में मान के रूप में उपयोग किए जाने पर समस्या को कैसे पैक किया जाता है। प्रत्येक मूल्य परिणामों के लिए एक संरचना को तत्काल करने के सीधी दृष्टिकोण को अनियमित मानों से संबंधित वाल्ग्रिंड त्रुटियों में लेना।
यहाँ चिंतित कोड है:
#include <gtest/gtest.h>
struct TestItem
{
const char * aString;
int anInt0;
int anInt1;
int anInt2;
};
class TestBase : public ::testing::Test, public ::testing::WithParamInterface<TestItem> {};
TEST_P(TestBase, TestAtoi)
{
TestItem item = GetParam();
std::cout << sizeof(TestItem) << std::endl;
ASSERT_FALSE(0); // actual test doesn't matter
}
INSTANTIATE_TEST_CASE_P(
TestBaseInstantiation,
TestBase,
::testing::Values(
TestItem { "0", 0, 0, 0 }
));
जब यह संकलित और जुड़ा हुआ है (मैं cmake साथ GTest बनाया):
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./gtest_valgrind
:
g++ gtest_valgrind.c -o gtest_valgrind -I gtest-1.7.0/include -L gtest-1.7.0/build -lgtest -lpthread -lgtest_main -std=c++11
और फिर साथ निष्पादित निम्नलिखित आउटपुट का उत्पादन होता है:
==17290== Memcheck, a memory error detector
==17290== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==17290== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==17290== Command: ./gtest_valgrind
==17290==
Running main() from gtest_main.cc
==17290== Use of uninitialised value of size 8
==17290== at 0x55B89F1: _itoa_word (_itoa.c:180)
==17290== by 0x55BC6F6: vfprintf (vfprintf.c:1660)
==17290== by 0x55E1578: vsnprintf (vsnprintf.c:119)
==17290== by 0x55C3531: snprintf (snprintf.c:33)
==17290== by 0x41F107: testing::(anonymous namespace)::PrintByteSegmentInObjectTo(unsigned char const*, unsigned long, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x41F1AA: testing::(anonymous namespace)::PrintBytesInObjectToImpl(unsigned char const*, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x41F252: testing::internal2::PrintBytesInObjectTo(unsigned char const*, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B8E: testing::internal2::TypeWithoutFormatter<TestItem, (testing::internal2::TypeKind)2>::PrintValue(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B63: std::basic_ostream<char, std::char_traits<char> >& testing::internal2::operator<< <char, std::char_traits<char>, TestItem>(std::basic_ostream<char, std::char_traits<char> >&, TestItem const&) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B3E: void testing_internal::DefaultPrintNonContainerTo<TestItem>(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B19: void testing::internal::DefaultPrintTo<TestItem>(char, testing::internal::bool_constant<false>, TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409ADB: void testing::internal::PrintTo<TestItem>(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== Uninitialised value was created by a stack allocation
==17290== at 0x404AAE: gtest_TestBaseInstantiationTestBase_EvalGenerator_() (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290==
==17290== Conditional jump or move depends on uninitialised value(s)
==17290== at 0x55B89F8: _itoa_word (_itoa.c:180)
==17290== by 0x55BC6F6: vfprintf (vfprintf.c:1660)
==17290== by 0x55E1578: vsnprintf (vsnprintf.c:119)
==17290== by 0x55C3531: snprintf (snprintf.c:33)
==17290== by 0x41F107: testing::(anonymous namespace)::PrintByteSegmentInObjectTo(unsigned char const*, unsigned long, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x41F1AA: testing::(anonymous namespace)::PrintBytesInObjectToImpl(unsigned char const*, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x41F252: testing::internal2::PrintBytesInObjectTo(unsigned char const*, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B8E: testing::internal2::TypeWithoutFormatter<TestItem, (testing::internal2::TypeKind)2>::PrintValue(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B63: std::basic_ostream<char, std::char_traits<char> >& testing::internal2::operator<< <char, std::char_traits<char>, TestItem>(std::basic_ostream<char, std::char_traits<char> >&, TestItem const&) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B3E: void testing_internal::DefaultPrintNonContainerTo<TestItem>(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B19: void testing::internal::DefaultPrintTo<TestItem>(char, testing::internal::bool_constant<false>, TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409ADB: void testing::internal::PrintTo<TestItem>(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== Uninitialised value was created by a stack allocation
==17290== at 0x404AAE: gtest_TestBaseInstantiationTestBase_EvalGenerator_() (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290==
==17290== Conditional jump or move depends on uninitialised value(s)
==17290== at 0x55BC742: vfprintf (vfprintf.c:1660)
==17290== by 0x55E1578: vsnprintf (vsnprintf.c:119)
==17290== by 0x55C3531: snprintf (snprintf.c:33)
==17290== by 0x41F107: testing::(anonymous namespace)::PrintByteSegmentInObjectTo(unsigned char const*, unsigned long, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x41F1AA: testing::(anonymous namespace)::PrintBytesInObjectToImpl(unsigned char const*, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x41F252: testing::internal2::PrintBytesInObjectTo(unsigned char const*, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B8E: testing::internal2::TypeWithoutFormatter<TestItem, (testing::internal2::TypeKind)2>::PrintValue(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B63: std::basic_ostream<char, std::char_traits<char> >& testing::internal2::operator<< <char, std::char_traits<char>, TestItem>(std::basic_ostream<char, std::char_traits<char> >&, TestItem const&) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B3E: void testing_internal::DefaultPrintNonContainerTo<TestItem>(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B19: void testing::internal::DefaultPrintTo<TestItem>(char, testing::internal::bool_constant<false>, TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409ADB: void testing::internal::PrintTo<TestItem>(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409AA6: testing::internal::UniversalPrinter<TestItem>::Print(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== Uninitialised value was created by a stack allocation
==17290== at 0x404AAE: gtest_TestBaseInstantiationTestBase_EvalGenerator_() (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290==
==17290== Conditional jump or move depends on uninitialised value(s)
==17290== at 0x55B9659: vfprintf (vfprintf.c:1660)
==17290== by 0x55E1578: vsnprintf (vsnprintf.c:119)
==17290== by 0x55C3531: snprintf (snprintf.c:33)
==17290== by 0x41F107: testing::(anonymous namespace)::PrintByteSegmentInObjectTo(unsigned char const*, unsigned long, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x41F1AA: testing::(anonymous namespace)::PrintBytesInObjectToImpl(unsigned char const*, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x41F252: testing::internal2::PrintBytesInObjectTo(unsigned char const*, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B8E: testing::internal2::TypeWithoutFormatter<TestItem, (testing::internal2::TypeKind)2>::PrintValue(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B63: std::basic_ostream<char, std::char_traits<char> >& testing::internal2::operator<< <char, std::char_traits<char>, TestItem>(std::basic_ostream<char, std::char_traits<char> >&, TestItem const&) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B3E: void testing_internal::DefaultPrintNonContainerTo<TestItem>(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B19: void testing::internal::DefaultPrintTo<TestItem>(char, testing::internal::bool_constant<false>, TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409ADB: void testing::internal::PrintTo<TestItem>(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409AA6: testing::internal::UniversalPrinter<TestItem>::Print(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== Uninitialised value was created by a stack allocation
==17290== at 0x404AAE: gtest_TestBaseInstantiationTestBase_EvalGenerator_() (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290==
==17290== Conditional jump or move depends on uninitialised value(s)
==17290== at 0x55B96DC: vfprintf (vfprintf.c:1660)
==17290== by 0x55E1578: vsnprintf (vsnprintf.c:119)
==17290== by 0x55C3531: snprintf (snprintf.c:33)
==17290== by 0x41F107: testing::(anonymous namespace)::PrintByteSegmentInObjectTo(unsigned char const*, unsigned long, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x41F1AA: testing::(anonymous namespace)::PrintBytesInObjectToImpl(unsigned char const*, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x41F252: testing::internal2::PrintBytesInObjectTo(unsigned char const*, unsigned long, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B8E: testing::internal2::TypeWithoutFormatter<TestItem, (testing::internal2::TypeKind)2>::PrintValue(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B63: std::basic_ostream<char, std::char_traits<char> >& testing::internal2::operator<< <char, std::char_traits<char>, TestItem>(std::basic_ostream<char, std::char_traits<char> >&, TestItem const&) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B3E: void testing_internal::DefaultPrintNonContainerTo<TestItem>(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409B19: void testing::internal::DefaultPrintTo<TestItem>(char, testing::internal::bool_constant<false>, TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409ADB: void testing::internal::PrintTo<TestItem>(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== by 0x409AA6: testing::internal::UniversalPrinter<TestItem>::Print(TestItem const&, std::ostream*) (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290== Uninitialised value was created by a stack allocation
==17290== at 0x404AAE: gtest_TestBaseInstantiationTestBase_EvalGenerator_() (in /home/davida/git/gitlab/fcdm/lwm2m.git/gtest_valgrind)
==17290==
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from TestBaseInstantiation/TestBase
[ RUN ] TestBaseInstantiation/TestBase.TestAtoi/0
24
[ OK ] TestBaseInstantiation/TestBase.TestAtoi/0 (76 ms)
[----------] 1 test from TestBaseInstantiation/TestBase (126 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (246 ms total)
[ PASSED ] 1 test.
==17290==
==17290== HEAP SUMMARY:
==17290== in use at exit: 0 bytes in 0 blocks
==17290== total heap usage: 239 allocs, 239 frees, 46,622 bytes allocated
==17290==
==17290== All heap blocks were freed -- no leaks are possible
==17290==
==17290== For counts of detected and suppressed errors, rerun with: -v
==17290== ERROR SUMMARY: 20 errors from 5 contexts (suppressed: 0 from 0)
यह बहुत सारे आउटपुट है, लेकिन अनिवार्य रूप से मुझे लगता है कि यह संकेत दे रहा है कि INSTANTIATE_TEST_CASE_P
में TestItem { "0", 0, 0, 0 }
लाइन के कारण तत्काल प्रारंभिक संरचना के बारे में कुछ असामान्य है।
ध्यान दें कि टेस्टआईटम का आकार 24 के रूप में आउटपुट है। 64-बिट सिस्टम पर, मुझे पूरा यकीन नहीं है कि इसे कैसे सुलझाना है। char *
के लिए 8 बाइट्स, और int
सदस्यों के लिए 4 * 3 = 12 बाइट्स। अगर वे 8 बाइट सीमाओं के साथ गठबंधन हैं, तो यह आकार 24 + 4 = 28 बाइट्स (या पैकिंग सहित 32 होना चाहिए) होना चाहिए। अगर वे 4 बाइट सीमाओं के साथ गठबंधन हैं, तो यह 20 होना चाहिए। कुछ ऐसा है जो मैं संरचना पैकिंग के बारे में नहीं समझता।
संरचना को अलग-अलग पैक करके वालग्रिंड चेतावनी को समाप्त किया जा सकता है। उदाहरण के लिए, इन संशोधनों के सभी तीन एक साफ valgrind रन में परिणाम:
#pragma पैक का उपयोग करना:
#pragma pack(1)
struct TestItem
{
const char * aString;
int anInt0;
int anInt1;
int anInt2;
};
कि 20
आउटपुट।
जीएनयू जी का उपयोग ++ पैकिंग विशेषता:
struct TestItem
{
const char * aString;
int anInt0;
int anInt1;
int anInt2;
} __attribute__((packed));
कि 20
भी आउटपुट।
अन्त में, struct करने के लिए एक डमी मूल्य जोड़ने:
struct TestItem
{
const char * aString;
int anInt0;
int anInt1;
int anInt2;
int anInt3; // add an extra member
};
24
आउटपुट है।
मेरे पास एक उचित मात्रा में प्रोजेक्ट कोड है जो मूल्य-पैरामीटर परीक्षणों के लिए इस सटीक तकनीक का उपयोग करता है, और सभी मामलों में वाल्ग्रिंड शिकायत करेगा यदि बचपन की रणनीतियों में से कोई एक का उपयोग नहीं किया जाता है।
मैं जानना चाहता हूं कि इस परीक्षण के लिए मूल्य बनाने के मेरे दृष्टिकोण के साथ मूलभूत रूप से कुछ गलत है या क्या यह कुछ मामलों का परिणाम है जो तत्काल परीक्षण मामलों के साथ करता है? या, सबसे अधिक संभावना है, यह एक gtest बग है?
धन्यवाद, यह समझ में आता है। हालांकि परीक्षण पास हो रहा है - 'ASSERT_FALSE (0)' सफल होगा, इसलिए डेटा का कोई डंप मुद्रित नहीं होता है। लेकिन मुझे लगता है कि आपका बिंदु अभी भी ध्वनि है - टेस्ट फ्रेमवर्क डेटा के माध्यम से 'आकार' के अनुसार स्कैनिंग और पैडिंग में अनियमित मूल्यों को पढ़ना चाहिए। – meowsqueak
@meowsqueak तो Gtest परीक्षण पास होने पर भी परीक्षण पैरामीटर मान मुद्रित करने का प्रयास कर रहा है। यह अजीब है, क्योंकि आप मानक आउटपुट में मुद्रित वास्तविक मूल्य नहीं देख सकते हैं, है ना? क्या आपने 'ऑपरेटर <<' को परिभाषित करने का प्रयास किया था? –
हां, मुझे लगता है कि यह कम से कम मूल्य पर एक स्नप्रिंट कर रहा है, भले ही यह इसे प्रिंट न करे। हो सकता है कि यह आउटपुट तैयार करता है ताकि वास्तव में परीक्षण चलाने वाले फ़ंक्शन को आवश्यक होने पर पूर्व-पका हुआ विवरण आसानी से प्रिंट कर सके। मेरे पास स्रोत है, मैं _could_ पता लगाना चाहिए कि मुझे क्या चाहिए। 'ऑपरेटर <<' को परिभाषित करने का आपका विचार अपेक्षित कार्य करता है, और वाल्ग्रिंड त्रुटि को समाप्त करता है। वैसे भी बफर डंप की तुलना में यह अधिक उपयोगी है, इसलिए मैं शायद इस परियोजना में इसका उपयोग करूंगा। – meowsqueak