web-dev-qa-db-fra.com

Debug assertion a échoué! Expression: __acrt_first_block == en-tête

J'essaie de tester la dll que j'ai écrit avec GoogleTest et lorsque j'appelle l'un des tests, cela me jette cette erreur:

enter image description here

J'en suis venu à la conclusion que le problème consiste à attribuer de la mémoire à des vecteurs, mais je ne sais pas comment le résoudre car je suis assez nouveau en programmation C++. Le code est comme suit:

#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;
}
12
Rok

S'agissant d'une DLL, le problème peut provenir de différents tas utilisés pour l'allocation et la désallocation (essayez de construire la bibliothèque de manière statique et vérifiez si cela fonctionnera).

Le problème est que les DLL et les modèles ne s'accordent pas très bien. En général, en fonction de la liaison du runtime MSVC, le problème peut être que la mémoire soit allouée dans l'exécutable et désallouée dans la DLL et vice-versa (car ils peuvent avoir des tas différents). Et cela peut arriver très facilement avec les modèles, par exemple: vous push_back () au vecteur à l'intérieur de removeWhiteSpaces () dans la DLL, de sorte que la mémoire de vecteur est allouée à l'intérieur de la DLL. Ensuite, vous utilisez le vecteur de sortie dans l'exécutable et une fois hors de portée, il est désalloué, mais à l'intérieur de l'exécutable dont le segment de mémoire ne sait rien du segment à partir duquel il a été alloué. Bang, tu es mort.

Cela peut être contourné si DLL et l'exécutable utilisent le même segment de mémoire. Pour garantir cela, la DLL et l'exécutable doivent utiliser le runtime MSVC dynamique - assurez-vous donc qu'ils sont tous deux liés au runtime de manière dynamique et non statique. En particulier, le fichier exe doit être compilé et lié à/MD [d] et la bibliothèque avec/LD [d] ou/MD [d] également, aucune des deux avec/MT [d]. Notez que par la suite, l'ordinateur qui exécutera l'application aura besoin de la bibliothèque d'exécution MSVC (par exemple, en installant "Visual C++ Redistributable" pour la version MSVC particulière).

Vous pouvez obtenir ce travail même avec/MT, mais c'est plus difficile: vous devez fournir une interface permettant aux objets alloués dans la DLL d'être également désalloués. Par exemple, quelque chose comme:

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

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

(Cependant, cela ne fonctionne pas très bien dans tous les cas, car il doit être appelé explicitement pour ne pas être appelé, par exemple, en cas d'exception. Pour résoudre cela correctement, vous devez fournir une interface à partir de la DLL, qui couvrira le vecteur sous le capot et prendra soin de la RAII appropriée)


EDIT: la solution finale consistait à intégrer tous les projets (les fichiers exe, dll et le projet googleTest dans son intégralité)/ Débogage multi-thread DLL (/ MDd) (les projets GoogleTest sont construits dans le débogage multi-thread (/ MTd) par défaut)

27
axalis

J'ai eu un problème similaire et il s'est avéré que mon projet unittest était défini sur une bibliothèque d'exécution de génération de code différente - par conséquent, définissez-le sur la même chose que le projet DLL, puis aucune exception de segment de mémoire 

2
serup

Je voyais aussi cette erreur et dans mon cas, tous les paramètres du modèle de mémoire étaient correctement alignés. Cependant, après avoir récemment mis à niveau les projets de vs2013 à vs2015, j'avais des références obsolètes entre les fichiers .exe et .dll. En fait, j'utilisais donc l'ancien DLL construit en 2013. Je devais supprimer la référence entre les fichiers. exe et .dll et rajoutez-le pour mettre à jour le nom du fichier .lib auquel le fichier exe était lié. (Cliquez avec le bouton droit de la souris sur l'élément enfant "Références" du projet .exe et sur "Ajouter", ce qui peut également porter à confusion, ce qui vous permet également de supprimer une référence).

1
fret