Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[c++] Czyżby to był błąd kompilatora?

Ostatnio zmodyfikowano 2013-05-31 16:16
Autor Wiadomość
f651144
Temat założony przez niniejszego użytkownika
[c++] Czyżby to był błąd kompilatora?
» 2013-05-30 19:34:50
Mam tu na myśli prawdziwy błąd kompilatora (tak, taki rzadko spotykany prawdziwy błąd). Oczywiście, mogę się mylić, ale wtedy wyjdzie mi to chyba na dobre bo ten post przyda się na coś i mnie, a jeśli tak nie jest, to pozwólcie, że się tu właduje (albowiem trochę zajęło mi dojście do tego co jest przyczyną i było to niezwykle frustrujące doświadczenie). Okej ale to rzeczy. Najnowszy kompilator dołączony do Code::Bolck'sa (wersja 4.7.1, 32 bit), obsługujący standart c++11, tworzy nie działający program z takiego oto kodu:
C/C++
int32_t socket::send( const std::string & buf, int32_t flags )
{
    int32_t res = declarations::socket_send( this->socket_handler, buf.c_str(), buf.size(), flags );
    if( res == value::socket_error )
    {
        return - 1;
    }
    //std::cerr << std::endl;
    return res;
}
gdzie declarations::socket_send jest stałym wskaźnikiem na standardową funkcje send z biblioteki WinSock. Co ciekawe taki kod działa bez problemu:
C/C++
int32_t socket::send( const std::string & buf, int32_t flags )
{
    int32_t res = declarations::socket_send( this->socket_handler, buf.c_str(), buf.size(), flags );
    if( res == value::socket_error )
    {
        return - 1;
    }
    std::cerr << std::endl;
    return res;
}
Jak to wyjaśnić? Dla sceptyków dodam, że pracuje pod systemem Windows 7 64-bit (Code::Blocks 12.11). Funkcja main programu:
C/C++
int main()
{
    system( "pause" );
    std::string http_get( "GET / HTTP/1.1\r\n"
    "Host: www.google.pl\r\n"
    "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0\r\n"
    "Accept: text/html,application/xhtml\r\n" //"+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
    "Accept-Language: pl,en-us;q=0.7,en;q=0.3\r\n"
    "Accept-Encoding: gzip, deflate\r\n"
    "Connection: keep-alive\r\n"
    "\r\n" );
    std::string answer( 100,( char ) 0 );
    ows::address::ipv4 addr( 62, 129, 232, 55 ); // Server cpp0x.pl :-)
    ows::socket s;
    std::cout << "Create:  " << s.create( SOCK_STREAM, IPPROTO_TCP ) << std::endl;
    std::cout << "Bind:    " << s.bind( 3490 ) << std::endl;
    std::cout << "Connect: " << s.connect( addr, 80 ) << std::endl;
   
    std::cout << "Send:    ";
    asm( "call_send:" );
    std::cout << s.send( http_get );
    std::cout << "/" << http_get.size() << std::endl;
   
    std::cout << "Recv:    " << s.recv( answer, 100, 0, false ) << std::endl;
    std::cout << "Answer:  " << answer << std::endl;
}
Wybaczcie wstawki asembler'owe. Kodu całej biblioteki wklejać oczywiście nie będę, bo nie ma to sensu. Oto dwa listingi dezasemblacji (pierwszy to ta niedziałająca wersja):
listing dezasemblacji x2
listing dezasemblacji x2
Alternatywne odnośniki do obrazka: Odnośnik 1, Odnośnik 2
O ile się nie mylę to na końcu (na czerwono) oznacza błąd w śledzeniu stack pointer'a, co już sugeruje, że coś jest nie tak.

Podsumowując: Co o tym myślicie? Mam rację twierdząc, że jest to błąd kompilatora? A może jestem ślepy i nie dostrzegam mojego błędu? Dodam jeszcze, że na starej wersji kompilatora (wersja 4.4.1, 32 bit) wszystko działa wyśmienicie...
P-84387
cyklopek11
» 2013-05-30 20:36:37
A co na Twój "trefny" program mówi OllyDBG ?
P-84399
pekfos
» 2013-05-30 20:41:33
tworzy nie działający program
Czyli jaki?

A co na Twój "trefny" program mówi OllyDBG ?
Zapewne nic. OllyDbg nie wykonuje takiej analizy kodu, jak IDA.
P-84400
Elaine
» 2013-05-30 20:53:25
O ile się nie mylę to na końcu (na czerwono) oznacza błąd w śledzeniu stack pointer'a, co już sugeruje, że coś jest nie tak.
Zdarza się całkiem często nawet w poprawnym kodzie, oznacza tylko tyle, że IDA nie umie się połapać w tym, co zrobił kompilator. Szczególnie, jeśli rzeczony kompilator robi ze stosem dość niestandardowe jak da daną platformę rzeczy.
P-84403
ison
» 2013-05-30 21:05:10
To, że po dodaniu
std::cerr << std::endl;
 program się nie wywala to o niczym nie świadczy. Powodów może być mnóstwo, najprawdopodobniej gdzieś piszesz po losowej pamięci. Szansa na to, że to jest błąd kompilatora jest znikoma.

Odpal chociażby GDB.
P-84406
f651144
Temat założony przez niniejszego użytkownika
» 2013-05-31 11:43:42
@pekfos: Niedziałający, czyli wykładający się przy wyjściu z funkcji socket::send. Przepraszam za to przemilczenie. Trochę okroiłem pierwszy post, by nie był za długi i, jak się okazuje, wyciąłem istotne szczegóły.

@Alueril: Zgadzam się na 100%. Zdarza się to całkiem często i nie oznacza, że coś jest nie tak, ale może to sugerować... :-)

@ison: Znów mój niewystarczający opis. Program źle zarządza stosem, przez co adresem powrotnym staje się 00000037 zamiast 00402852. Jeśli ja jestem winny, to błąd musi być gdzieś wewnątrz funkcji socket::send, bo tylko tam program ma możliwość zmiany adresu powrotu z funkcji.

@cyklopek11: Co na to OllyDBG? Otóż okazuje się, że wywołanie send zmienia wartość esp, co powoduje błąd. Wartość esp zmienia się o dokładnie 4*4 bajty (czyli rozmiar argumentów send - nie mam zielonego pojęcia, czy to ma jakieś znaczenie).
0028FE68  00 00 00 00
0028FE6C  52 28 40 00  <- "Słuszny" adres powrotu  |
0028FE70  F4 FE 28 00                              |
0028FE74  00 00 00 00                              | przeskok o 4x4 bajty
0028FE78  E8 00 00 00                              |
0028FE7C  37 00 00 00  <- Adres powrotu            |
0028FE80  22 10 98 77
Z tego natychmiast wynika też to, dlaczego drugi program działa. Kompilator używa tam leave, co przywraca poprawną wartość esp.
P-84440
cyklopek11
» 2013-05-31 12:47:05
Myślę, że jeśli chcesz zawodowo zajmować się inżynierią wsteczną, szukaniem bugów itd. to w przypadku faktycznego błędu kompilatora, twoje śledztwo i odkrycie będzie czymś co można zamieścić w CV (oczywiście szybka  publikacje np. na swojej stronie , wiadomość do zespołu GCC). Oczywiście takich wpisów w CV potrzebujesz dziesiątki aby się liczyć na świecie :-)

Jeśli Ci nie zależy na tym, to warto pytanie postawione w temacie postu zadać ekspertowi. Tutaj od razu nasuwa się: Gynvael Coldwind .
P-84454
pekfos
» 2013-05-31 13:09:20
Za mało danych by cokolwiek powiedzieć. Prawdopodobieństwo, że to błąd, jest bardzo małe. Zwłaszcza, że uszkodzenie stosu to nie jest byle co i twórcy kompilatora na pewno by to znaleźli w czasie testów.

twoje śledztwo
Tematy na forach, itp ;)
P-84456
« 1 » 2
  Strona 1 z 2 Następna strona