Mam następujący komunikat "wyjątek pierwszej szansy", który pochodzi z biblioteki DLL, którą napisałem, działającej w pliku wykonywalnym, którego nie napisałem. Oznacza to, że DLL jest wtyczką. Przy pierwszym uruchomieniu tego wyjątku próba otwarcia pliku mapy pamięci współużytkowanej kończy się niepowodzeniem. Jeśli zignoruję wyjątki pierwszej szansy i po prostu uruchomię, aplikacja w końcu zawiesza się lub ulega awarii.Jak mogę debugować lub naprawiać problem nieskończonej pętli i sterty korupcji z udziałem boost :: interprocess managed_shared_memory?
First-chance exception at 0x76a7c41f in notmyexe.exe: Microsoft C++ exception: boost::interprocess::interprocess_exception at memory location 0x002bc644..
Po kilku godzinach wydaje się, że jest spowodowany blokiem kodu, który bez przerwy przechodzi w pętlę, dopóki nie zostanie spełniony oczekiwany warunek wyjątku. Okazuje się, że jeśli nigdy nie zostanie wyczyszczone, a następnie, w końcu, ten wyjątek zamienia się w inny stan wyjątku niskiego poziomu i/lub przekształca się w uszkodzenie sterty. Wszystko to jest po to, aby otworzyć wspólny obszar pamięci za pomocą Boost :: interprocess. Pierwszą rzeczą, która komplikuje sytuację, jest to, że w moim projekcie opartym na Visual C++ 2008 pierwszy wyjątek boost::interprocess::interprocess_exception
pierwszej szansy nie jest generowany i identyfikowany jako lokalizacja, z której pochodzi, ponieważ kompilator Visual C++ 2008 nie może znaleźć złożonego wzmocnienia -tygodny kod szablonów. Jednak przez pojedyncze przejście przez widok asemblerowy znalazłem kod, który się podniósł.
Linia najwyższego poziomu od własnego kodu, który to wszystko zaczyna się psuć na to:
segment = new managed_shared_memory( open_or_create
, MEMORY_AREA_NAME
, SHARED_AREA_SIZE);
Powyższy managed_shared_memory
klasa jest od interprocess_fwd.hpp i jest standardową częścią doładowania pamięci dzielonej API/nagłówki. Ponieważ jest oparty na szablonie, powyższe rozwija się w około 2Kchars długie wyrażenie szablonu doładowania C++, które jest obcięte na różne długości przez linker i przez debugger. W Visual C++ 2008 nie ma już możliwości debugowania kodu źródłowego, wydaje się, że limity te są w grze.
Na przykład, kiedy wysadza otrzymuję ten stosu wywołań:
KernelBase.dll!76a7c41f()
[Frames below may be incorrect and/or missing, no symbols loaded for KernelBase.dll]
KernelBase.dll!76a7c41f()
> msvcr90d.dll!_malloc_dbg(unsigned int nSize=2290875461, int nBlockUse=264, const char * szFileName=0x01fcb983, int nLine=1962999808) Line 160 + 0x1b bytes C++
8bfc4d89()
Nie rzeczywisty użytkownik końcowy napisane funkcje źródłowe pojawiają się w stosie zrzutu powyżej.
Jak mam to debugować? Po drugie, czy jest jakiś znany problem z interpretercją doładowania, z Visual C++ 2008? Po trzecie, co robi poniższy kod doładowania i dlaczego musi się bez końca zapętlać?
boost::interprocess::basic_managed_shared_memory<char,
boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,
boost::interprocess::offset_ptr<void,int,unsigned int,0>,0>,
boost::interprocess::iset_index>::basic_managed_shared_memory<char,boo...
Kolejne warstwy w dół, mamy do:
basic_managed_shared_memory (open_or_create_t,
const char *name, size_type size,
const void *addr = 0, const permissions& perm = permissions())
: base_t()
, base2_t(open_or_create, name, size, read_write, addr,
create_open_func_t(get_this_pointer(),
ipcdetail::DoOpenOrCreate), perm)
{}
Tak czy inaczej, nie próbuj do debugowania tego w domu dzieci, oto co się dzieje:
Wreszcie, używając mojej ninja-podobnej zdolności do przejścia przez kilka milionów linii języka asemblerowego, pokonałem ograniczenia zła debuggera Visual C++ 2008 i znalazłem kod w qu estion.
To jest to, co wysadza w rzeczywistości: create_device<FileBased>(dev...
.
Niektóre kontekst tutaj: managed_open_or_create_impl.h linia 351 ...
else if(type == DoOpenOrCreate){
//This loop is very ugly, but brute force is sometimes better
//than diplomacy. If someone knows how to open or create a
//file and know if we have really created it or just open it
//drop me a e-mail!
bool completed = false;
while(!completed){
try{
create_device<FileBased>(dev, id, size, perm, file_like_t()); // <-- KABOOM!
created = true;
completed = true;
}
catch(interprocess_exception &ex){
if(ex.get_error_code() != already_exists_error){
throw;
}
else{
try{
DeviceAbstraction tmp(open_only, id, read_write);
dev.swap(tmp);
created = false;
completed = true;
}
catch(interprocess_exception &e){
if(e.get_error_code() != not_found_error){
throw;
}
}
catch(...){
throw;
}
}
}
catch(...){
throw;
}
thread_yield();
}
}
+1 za odręczną twarz z grymasem odręcznym. –
Jest tu dużo do pochłaniania, ale czy rozważałeś możliwość, że wyjątek pierwszej szansy może być całkowicie łagodny? –
Wprowadziłem kilka zmian i usunąłem to, co było bardzo nieprofesjonalne w tym pytaniu. Przepraszam za każdego, kto musiał przeczytać oryginalną wersję. –