2009-08-04 10 views
6

Używam dodatku SP1 dla programu Visual C++ 2008. Mam aplikację skompilowaną w trybie debugowania, ale połączoną z biblioteką w trybie zwolnienia.Łączenie z biblioteką w wydaniu i .exe w przypadku błędów debugowania w Visual Studio

Występuje awaria podczas uruchamiania aplikacji. Aby problem mniejszy, stworzyłem proste rozwiązanie z 2 projektów:

  • lib_release (generuje .lib, w trybie uwalniania)
  • exec_using_lib_release (genereates .exe, w trybie debugowania)

projekt „lib_release” jest na tyle prosty, aby mieć prostą klasę:

//Foo.h 
#include <vector> 
class Foo { 
    std::vector<int> v; 
    public: 
    void doSomething(); 
}; 
//Foo.cpp 
#include "Foo.h" 
void Foo::doSomething() {} 

projekt „exec_using_lib_release” jest prosta tak:

//main.cpp 
#include "Foo.h" 
int main() { 
    Foo foo; 
    foo.doSomething(); 
    return 0; 
} 

To się zawiesza, to ten sam problem zgłoszony przez How do you build a debug .exe (MSVCRTD.lib) against a release built lib (MSVCRT.lib)?, ale jego odpowiedź nie zadziałała.

Otrzymuję te same ostrzeżenia o linkerze, próbowałem wykonać te same kroki, ale żadna nie działała. Czy jest coś, czego mi brakuje?

EDIT:

Na lib_release (który tworzy bibliotekę w trybie uwalniania), używam multi gwintowanych (/ MT), a na exec_using_lib_release używam multi gwintowanych Debugowanie (/ MTd). Myślę, że jest to oczekiwany sposób robienia tego, ponieważ chcę aby plik .lib był tworzony bez informacji debugowania. Przeczytałem dokument pod numerem MSDN Runtime library, a są to ustawienia łączenia z CRT w sposób statyczny.

Nie mam również "Wspierania wspólnego środowiska językowego".

+0

Jest to dokładna przykładowy kod (Foo.h) czy jest to uproszczony, a nie to, czego naprawdę próbował? – Timbo

+0

@Timbo to prawie to samo, tylko klasa Foo ma wersję .cpp, która ma zaimplementowaną metodę doSomething(). –

+0

Czy jesteś dostawcą statycznej biblioteki, czy jest to strona trzecia? – KJAWolf

Odpowiedz

8

Nie musisz mieć używać tych samych środowisk uruchomieniowych dla modułów wydania i debugowania (ale to pomaga), o ile przestrzegasz bardzo szczegółowych zasad: nigdy nie mieszaj i nie dopasowuj dostępu do pamięci przydzielonej przy użyciu każdego środowiska wykonawczego. Mówiąc prościej, jeśli masz rutynę w bibliotece dll, która przydziela trochę pamięci i zwraca ją do osoby dzwoniącej, osoba dzwoniąca nie może jej zwolnić - musisz utworzyć funkcję w oryginalnej bibliotece dll, która zwalnia pamięć. W ten sposób jesteś bezpieczny od niedopasowań środowiska wykonawczego.

Jeśli uważasz, że biblioteki Windows są zbudowane tylko w wersji release (chyba że masz wersję debugowania systemu Windows), ale używasz ich z aplikacji do debugowania, zobaczysz, jak to ma znaczenie.

Twój problem polega na tym, że używasz biblioteki statycznej, nie ma już granicy dll, a wywołania w bibliotece są kompilowane przy użyciu statycznej wersji środowiska wykonawczego C. Jeśli twój exe używa dynamicznej wersji dll środowiska wykonawczego, okaże się, że linker używa tego, zamiast tego, którego używa twoja statyczna biblioteka ... i dostaniesz awarie.

Możesz więc odbudować swoją bibliotekę jako bibliotekę DLL; lub możesz upewnić się, że obie używają tej samej biblioteki CRT; lub możesz upewnić się, że oba używają tego samego typu CRT - tj. wersji dll lub wersji statycznej, zachowując różnice debugowania/wydania.

Przynajmniej, myślę, że to jest twój problem - jakie są ustawienia "generowania kodu i biblioteki uruchomieniowej"?

+0

Tak, to jest mój problem. Jednak w jaki sposób programiści lib, którzy wydadzą swoje biblioteki skompilowane jako "wydanie", czynią ich "połączonymi" z programem działającym w trybie debugowania? Czy przestrzegają tych "surowych zasad", o których mówisz? –

+0

używasz statycznego lub dynamicznego CRT w naszej bibliotece? Jeśli chcesz, aby był całkowicie przenośny, użyj wersji statycznej, ponieważ wszystkie wywołania CRT zostaną osadzone w bibliotece. Alternatywnie zbuduj swój exe z wydaniem CRT. Nie jestem pewien, czy istnieje wiele komercyjnych statycznych bibliotek, ludzie zamiast tego dostarczają biblioteki dll. – gbjbaanb

+0

W związku z tymi konkretnymi regułami Czy w przypadku trybów debug-release może występować jakiś problem z różnymi pakietami? – TripleS

2

Problem polega na tym, że debugowanie będzie korzystać z wersji debugowania środowiska wykonawczego c, a wersja będzie korzystała z wersji release środowiska wykonawczego c, a próba dostępu do pamięci przez granicę dll będzie w złym stanie czas i awarię. Najlepiej używać tylko kompilacji debugowania razem (lub wydać)

+1

, gdzie widzisz alokację dynamiczną? –

5

W przypadku kombinacji problemów związanych z wydaniem i debugowaniem, o których wspominali wcześniejsi ludzie, problemy te nie pojawiały się, dopóki niewłaściwa biblioteka środowiska wykonawczego nie próbowała anulować alokacji. Myślę, że to, co napotkasz, to że VS 2008 ma domyślnie włączone debugowanie iteratora, więc twoja lib i twój exe odwołują się do różnych implementacji std :: vector. Będziesz chciał dodać _HAS_ITERATOR_DEBUGGING = 0 do ustawień preprocesora. Wtedy zaczniesz uderzać w problem różnych hałd dla różnych runtimes. W przeszłości mieliśmy różne zasady i zasady, aby tego uniknąć, ale teraz polegamy tylko na spójnym środowisku kompilacji - nie mieszaj i nie łącz.

0

Załączona biblioteka nie powinna współużytkować zasobów CRT na granicy biblioteki. Dla kodu C dynamicznie przydzielona pamięć musi zostać zwolniona po tej samej stronie granicy. Dla kodu C++ można użyć przestrzeni nazw standardowej wewnątrz biblioteki DLL, ale te obiekty, które używają przestrzeni nazw standardowej, powinny zostać przekazane poza granicę biblioteki.

zobaczyć this odpowiedź na podobne pytanie

Powiązane problemy