2016-02-10 8 views
7

मैं dll जो मैं GoogleTest के साथ लिखा था और जब मैं परीक्षणों में से एक कॉल यह मुझे इस त्रुटि फेंकता परीक्षण करने के लिए कोशिश कर रहा हूँ:डीबग सम्मिलन विफल! अभिव्यक्ति: __acrt_first_block == हैडर

enter image description here

मैं इस निष्कर्ष पर आ गए हैं कि समस्या वेक्टरों को स्मृति आवंटित करने में है, लेकिन मुझे नहीं पता कि इसे कैसे हल किया जाए क्योंकि मैं सी ++ प्रोग्रामिंग के लिए बिल्कुल नया हूं। कोड इस प्रकार है:

#ArraysCPP11.h 
#ifdef ARRAYSCP11_EXPORTS 
#define ARRAYSCP11_API __declspec(dllexport) 
#else 
#define ARRAYSCP11_API __declspec(dllimport) 
#endif 

__declspec(dllexport) void removeWhiteSpaces(std::vector<std::string> v, std::vector<std::string> &output); 
#ArraysCPP11.cpp 
void removeWhiteSpaces(std::vector<std::string> v, std::vector<std::string> &output) { //odstranjevanje presledkov iz vector-ja (vsak drugi element je bil presledek) 
    for (std::vector<std::string>::iterator it = v.begin(); it != v.end(); it++) { 
     std::string buffer = *it; 
     if (isdigit(buffer[0])){; 
      output.push_back(*it); 
     } 
    } 
} 
#TestTemp.h 

template<class T> 
class TestTemp 
{ 
public: 
    TestTemp(); 
    void SetValue(T obj_i); 
    T GetValue(); 
    bool alwaysTrue(); 
    bool TestTemp<T>::formattingTest(std::string input, std::vector<std::string> realVector, std::vector<std::string> formattedInput); 
private: 
    T m_Obj; 
}; 

template<class T> 
inline bool TestTemp<T>::formattingTest(std::string input, std::vector<std::string> realVector, std::vector<std::string> formattedVector) { 
std::string input2 = input; 
// std::vector<std::string> fResult; 
std::string first; 
std::string second; 
bool endResult = true; 
std::vector<std::string> end; 
//std::vector<std::string> result = split(input2, ' '); 
removeWhiteSpaces(formattedVector,end); 
std::vector<std::string>::iterator yt = realVector.begin(); 
for (std::vector<std::string>::iterator it = end.begin(); it != end.end(); it++, yt++) { 
    first = *it; 
    second = *yt; 
    if (first.compare(second) != 0) { 
     endResult = false; 
     break; 
    } 
} 
return endResult; 
} 
#ArraysCPP11-UnitTest.cpp 
struct formattingTesting{ 
    // formattingTesting* test; 
    std::string start; 
    std::vector<std::string> endResult; 
    formattingTesting() { 
    } 
    explicit formattingTesting(const std::string start, const std::vector<std::string> endResult) 
    : start{start}, endResult{endResult} 
    { 
    } 
}; 

struct fTest : testing::Test { 
    formattingTesting* test; 
    fTest() { 
     test = new formattingTesting; 
    } 
    ~fTest() { 
     delete test; 
    } 
}; 

struct format { 
    std::string start; 
    std::vector<std::string> end; 
}; 

struct formTest : fTest, testing::WithParamInterface<format> { 
    formTest() { 
     test->start = GetParam().start; 
     test->endResult = GetParam().end; 
    } 
}; 

TEST_P(formTest, test1) { 
    bool endResult = true; 
    TestTemp<int> TempObj; 
    std::string first; 
    std::string second; 
    //std::string start ("1 2 3 4 5 6 7 8 9 10"); 
    //std::vector<std::string> end = { "1","2","3","4","5","6","7","8","9","10" }; 
    std::vector<std::string> start2 = { "1","","2","3","4","5","6","7","8","9","10" }; 
    std::string start = GetParam().start; 
    std::vector<std::string> end = GetParam().end; 
    bool result = TempObj.formattingTest(start,end,start2);  
    EXPECT_TRUE(result); 
} 

INSTANTIATE_TEST_CASE_P(Default, formTest, testing::Values(
    format{ "1", {"1"} }, 
    format{ " ", {} }, 
    format{ "1 2 3 4 5",{"1","2","3","4","5"} }, 
    format{ "1 2 3 4 5 6", {"1","2","3","4","5","6"} } 
)); 


int main(int argc, char** argv) 
{ 
    testing::InitGoogleTest(&argc, argv); 
    RUN_ALL_TESTS(); 
    return 0; 
} 
+0

आपके कोड में * अपरिभाषित व्यवहार * है। आपके पास 'स्टार्ट 2' वेक्टर में एक खाली स्ट्रिंग है, जिसे आप अंततः 'removeWhiteSpace' फ़ंक्शन' पर पास करते हैं, जहां आप वेक्टर में तारों के पहले अक्षर तक पहुंचते हैं। यदि एक स्ट्रिंग खाली है, तो इसका पहला अक्षर नहीं है, इसलिए आप सीमाओं से बाहर अनुक्रमणित कर रहे हैं। इसके अलावा 'removeWhiteSpace' नाम बहुत अच्छा नहीं है, क्योंकि फ़ंक्शन वास्तव में सफेद-स्थान को नहीं हटाता है, यह केवल जांचता है कि स्ट्रिंग का पहला अक्षर एक अंक है या नहीं (गलत जैसा मैंने अभी उल्लेख किया है)। –

+0

@JoachimPilebog वेक्टर 'start2' मुख्य रूप से परीक्षण के तुलना भाग (कोड को हटाने के बाद' कोड के हिस्से को डीबग करने के लिए उपयोग किया जाता है) और समस्या को ठीक करने के बाद हटा दिया जाएगा। साथ ही फ़ंक्शन 'removeWhiteSpaces' वास्तव में सफेद-स्थान को हटा देता है क्योंकि यह केवल उन तत्वों को धक्का देता है जो नए वेक्टर – Rok

+0

बीटीडब्ल्यू में अंक हैं। आप कॉन्स्ट संदर्भ द्वारा उन्हें पास करने के बजाय वेक्टरों की प्रतिलिपि क्यों प्रतिलिपि बनाते हैं (उदाहरण के लिए 'removeWhiteSpaces (std :: vector v, ...) में जहां आप केवल वेक्टर v को देखते हैं, इसलिए इसे होने की आवश्यकता नहीं है गैर स्थिरांक)। – axalis

उत्तर

15

इस के रूप में एक DLL है, समस्या अलग आवंटन और आवंटन रद्द करने के लिए इस्तेमाल किया ढेर में झूठ सकता है (पुस्तकालय स्थिर बनाने और अगर जाँच करने के लिए कोशिश वह काम करेगा)।

समस्या यह है कि डीएलएल और टेम्पलेट्स एक साथ सहमत नहीं हैं। सामान्य रूप से, एमएसवीसी रनटाइम के लिंक के आधार पर, यह समस्या हो सकती है अगर स्मृति निष्पादन योग्य में आवंटित की जाती है और डीएलएल में विघटित होती है और इसके विपरीत (क्योंकि उनके पास अलग-अलग ढेर हो सकते हैं)। और यह टेम्पलेट्स के साथ बहुत आसानी से हो सकता है, उदाहरण के लिए: DLL में removeWhiteSpaces() के अंदर वेक्टर को push_back(), इसलिए वेक्टर मेमोरी डीएलएल के अंदर आवंटित की जाती है। फिर आप निष्पादन योग्य में आउटपुट वेक्टर का उपयोग करते हैं और एक बार जब यह गुंजाइश हो जाता है, तो इसे हटा दिया जाता है, लेकिन निष्पादन योग्य के अंदर जिसका ढेर ढेर के बारे में कुछ भी नहीं जानता है, इसे आवंटित किया गया है। बैंग, तुम मर चुके हो

यह डीएलएल और निष्पादन योग्य दोनों ही ढेर का उपयोग करते समय काम किया जा सकता है। यह सुनिश्चित करने के लिए, डीएलएल और निष्पादन योग्य दोनों को गतिशील एमएसवीसी रनटाइम का उपयोग करना चाहिए - इसलिए सुनिश्चित करें कि रनटाइम दोनों गतिशील रूप से लिंक हैं, स्थिर रूप से नहीं। विशेष रूप से, एक्सई को संकलित और/एमडी [डी] और पुस्तकालय/एलडी [डी] या/एमडी [डी] के साथ जोड़ा जाना चाहिए, न तो एक/एमटी [डी] के साथ। ध्यान दें कि बाद में कंप्यूटर जो ऐप चलाएगा, उसे चलाने के लिए एमएसवीसी रनटाइम लाइब्रेरी की आवश्यकता होगी (उदाहरण के लिए, विशेष एमएसवीसी संस्करण के लिए "विजुअल सी ++ पुनर्वितरण योग्य" स्थापित करके)।

आप उस काम को/एमटी के साथ भी प्राप्त कर सकते हैं, लेकिन यह अधिक कठिन है - आपको कुछ इंटरफ़ेस प्रदान करने की आवश्यकता होगी जो डीएलएल में आवंटित वस्तुओं को भी हटा दिया जाएगा। जैसे उदाहरण कुछ के लिए:

__declspec(dllexport) void deallocVector(std::vector<std::string> &x); 

void deallocVector(std::vector<std::string> &x) { 
    std::vector<std::string> tmp; 
    v.swap(tmp); 
} 

(लेकिन यह सभी मामलों में बहुत अच्छी तरह से काम नहीं करता है, के रूप में यह स्पष्ट रूप से कहा जा तो यह अपवाद के मामले में जैसे कहा जाता है नहीं किया जाएगा की जरूरत है - ठीक से इस को हल करने के क्या तुम करोगी डीएलएल से कुछ इंटरफ़ेस प्रदान करने की आवश्यकता है, जो हुड के नीचे वेक्टर को कवर करेगा और उचित RAII का ख्याल रखेगा)

संपादित करें: अंतिम समाधान वास्तव में सभी परियोजनाओं (exe, dll और संपूर्ण googleTest प्रोजेक्ट) मल्टी-थ्रेडेड डीबग डीएलएल (/ एमडीडी) में निर्मित (GoogleTest प्रोजेक्ट्स डिफ़ॉल्ट रूप से मल्टी-थ्रेडेड डीबग (/ एमटीडी) में बनाए गए हैं)

+0

मैं कोशिश करने जा रहा हूं लेकिन दुख की बात है कि मुझे इसे डीएलएल के रूप में काम करने के लिए एक रास्ता खोजने की जरूरत है क्योंकि मेरे पर्यवेक्षक इसे – Rok

+0

पसंद करते हैं, जवाब को अपडेट किया गया है, आपको मूल रूप से गतिशील रनटाइम के खिलाफ इस तरह से बचने के लिए लिंक करने की आवश्यकता है समस्याओं का – axalis

+0

इसलिए यदि मैं सही ढंग से समझ रहा हूं तो मुझे exe के रनटाइम लाइब्रेरी को/MD और डीएलएल में से एक/एलडी सही करने की आवश्यकता है? यदि ऐसा है, तो मैं वास्तव में डीएलएल के लिए ऐसा नहीं कर सकता क्योंकि मुझे/एलडी विकल्प मुझे नहीं दिया गया है – Rok

संबंधित मुद्दे