Compiler kennt unbekannte Variable?



  • Hi,

    also manchmal stehe ich wirklich vor einem Rätsel, hier z.B. (ihr müsst die Fkt. nicht komplett lesen)

    void UDPSocket::sendData( const sockaddr_in& dest, unsigned long size )
    {
            // First naive try to send the thing out
            long sent = sendto( m_socket, m_buffer, size, 0, reinterpret_cast<
                    const sockaddr* >( &dest ), sizeof( dest ) );
    
            // If sending did not succeed...
            unsigned long retries = 0;
            while ( sent == -1 && retries++ < m_sendRetries )
            {
                    // Permanent error?
                    if ( errno != EAGAIN )
                            SERPENTESERROR( "sendto() failed!" );
    
                    // ...wait for buffer to clear
                    fd_set fd;
                    FD_ZERO( &fd );
                    FD_SET( m_socket, &fd );
    
                    timeval t;
                    memset( &t, 0, sizeof( t ) );
                    t.tv_sec = 0;
                    t.tv_usec = m_selectTimeoutUsec;
    
                    select( m_socket + 1, 0, &fd, 0, &t );
    
                    // Now either the buffer is clear or the select() call has tiemd out so
                    // let's try again
                    sent = sendto( m_socket, m_buffer, size, 0, reinterpret_cast<
                            const sockaddr* >( &dest ), sizeof( dest ) );
    
                    debugLog( toString( dest ) + " Buffer full, retrying..." );
            }
    
            if ( sent == -1 )
                    SERPENTESERROR( "Gave up sending an UDP packet." );
            else if ( sent != ( long )size )
                    SERPENTESERROR( "Packet partially sent? (" + toString( sent ) +
                            " bytes of " + toString( size ) + " sent)" );
    
            debugLog( toString( dest ) + " " + toString( read ) + " bytes sent." );
    }
    

    Interesant ist die letzte Zeile der Funktion. Dort verwende ich eine Variable namens read (die durch C&P-Fehler meiner Empfangen-Funktion entstanden ist), die in dieser Methode nirgends definiert wird, auch gibt es keine globale Variable mit diesem Namen und keine Funktion (wobei der Compiler mit dieser Schreibweise ja eh keine Funktion aufrufen könnte).

    Trotzdem gibt er lustigerweise folgendes aus:

    127.0.0.1:1337 1 bytes sent.

    Wie zum Teufel kommt er hier auf 1?!

    ChrisM



  • Stell nen minimales, kompilierbares Beispiel zusammen und gut is.



  • Ist das vielleicht die Problematik?

    #include <iostream>
    #include <windows.h>
    
    int main()
    {
    	std::cout << MessageBox << std::endl;
    }
    


  • Vielleicht ist in einem Header (der nicht von dir ist) ein Makro namens read. Gaaanz böse! Hatt ich schon mal, das ich eine Variable komplett groß geschrieben habe (ich glaub MAXIMUM). ALs ich sie benutzen wollte, hat der Compiler gemeckert, das es ein fehler gibt. Ich wußte nicht wieso. Am Ende stellte sich raus, das es ein Makro von MS war, das natürlich meine Variable bei Benutzung ersetzt hatte.



  • Vergesst es...



  • Hi,

    Problem reduziert:

    #include <string>
    #include <iostream>
    
    int main( void )
    {
            std::cout << read << std::endl;
            return 0;
    }
    

    Nur kommt hier jetzt eine Warnung:

    chris@daedalus ~/Coding $ g++ -Wall -Wextra -ansi -pedantic -I/usr/include/SDL -D_REENTRANT test.cpp
    test.cpp: In function int main()': test.cpp:6: warning: the address of \ssize_t read(int, void*, size_t)', will always evaluate as `true'

    Warum kommt die Warnung bei meinem Projekt nicht, obwohl ich dort genau mit den gleichen Schaltern compiliere?
    Siehe http://cvs.sourceforge.net/viewcvs.py/serpentes/serpentes/Makefile?view=markup

    ChrisM



  • Was ist die Signatur von toString?



  • Hi,

    ganz simpel...

    template< typename T >
            std::string toString( T value )
            {
                    std::ostringstream stringStream;
                    stringStream << value;
                    return stringStream.str();
            }
    
            std::string toString( const struct sockaddr_in& addr );
    

    ChrisM



  • Weil in Deinem Fall eine Funktion mit der Funktionspointersignatur (tolles Wort 🙄) von read erstellt wird. Das wäre dann also:

    std::string toString( ssize_t (*read)(int, void*, size_t) value )
    {
       std::ostringstream stringStream;
       stringStream << value;
       return stringStream.str();
    }
    

    value ist also ein Zeiger auf eine Funktion. Diesen Zeiger darf man nach bool casten und der kann true oder false ergeben, je nachdem ob Du einen NULL-Zeiger reinsteckst. Das kann der Compiler an der Stelle ja nicht wissen.
    Bei Deiner Ausgabe (mit Warning) wird das read direkt in einen bool gecastet und da weiss der Compiler, dass gibt immer true.



  • Hi,

    aber in meiner toString()-Templatefunktion caste ich in der zweiten Zeile doch auch direkt nach bool, oder?

    ChrisM



  • Das ist aber ein Cast wie in der folgenden Routine:

    void f( void* x)
    {
      if( x) {
        cout << "true" << endl;
      }
    }
    

    Der Compiler warnt bei der Abfrage doch auch nicht. x könnte ja auch NULL sein und damit falsch.
    In Deiner Template Methode ist es genauso. Dein Template Parameter könnte ja ein NULL Pointer sein.
    In Deiner direkten Ausgabe mit cout << read kann read nie ein NULL Pointer sein.



  • Hi,

    ach so ja klar, habs verstanden.

    Vielen Dank! 🙂

    ChrisM


Anmelden zum Antworten