Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Faule Socke

Community-Fossil

  • »Faule Socke« ist der Autor dieses Themas

Beiträge: 1 915

Wohnort: Schreibtischstuhl

  • Private Nachricht senden

1

01.01.2008, 16:36

...Stack around the variable 'IP' was corrupted.

Hi,

ich hab da ne fiese debuggermeldung, die man zwar überspringen kann, aber ist ja trotzdem scheisse.

Zitat


Run-Time Check Failure #2 - Stack around the variable 'IP' was corrupted.


Hier noch ein bisschen Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void CApplication::AddAddress()
{
    //! Adds an address to the list.

    NetStream::CIP  IP;
    ETargetType     Type;
    char            acBuffer[64];

    std::cout << "IP: "; std::cin.getline(acBuffer, 64);    IP.SetH(acBuffer);
    std::cout << "Type: "; std::cin.getline(acBuffer, 64);
    switch(tolower(acBuffer[0]))
    {
    case 's':   Type    =   TYPE_SERVER;        break;
    case 'w':   Type    =   TYPE_WORKSTATION;   break;
    default:    std::cout << "Unknown type!"; std::cin.sync(); std::cin.get(); return;
    }

    std::cout << "New ID: " << m_Targets.AddIP(IP, Type)->usID;
}   // <-- Hier tritt angeblich der Fehler auf.


So hier noch der Code von AddIP.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
PingTargetVecIt CTargetList::AddIP(const NetStream::CIP &IP, const ETargetType &Type)
{
    SPingTarget Target;
    Target.IP   =   IP;
    Target.Type =   Type;
    Target.usID =   m_Targets.size();
    m_Targets.push_back(Target);
    return FindEntryByID(Target.usID);
}


Noch der Code von FindEntryByID:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
PingTargetVecIt CTargetList::FindEntryByID(const unsigned short usID)
{
    for(PingTargetVecIt It = m_Targets.begin(); It != m_Targets.end(); It++)
    {
        if(It->usID == usID)
            return It;
    }

    return m_Targets.end();
}


Und hier die noch ne Struktur und nen paar typedefs:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Target type enumeration


enum ETargetType
{
    TYPE_SERVER         =   0,
    TYPE_WORKSTATION    =   1
};


// Address structure


struct SPingTarget
{
    unsigned short      usID;
    NetStream::CIP      IP;
    ETargetType         Type;
};

const bool operator == (const SPingTarget &Left, const SPingTarget &Right);

typedef std::vector<SPingTarget>        PingTargetVec;
typedef PingTargetVec::iterator         PingTargetVecIt;
typedef PingTargetVec::const_iterator   PingTargetVecConstIt;


Infos zum Programm: Das soll ein kleiner Pinger werden. Man kann IPs eintragen die werden dann überprüft.
Wenn man als Typ Server angegeben hat, soll es Später ne meldung geben, wenn der offline ist, Das programm ist aber noch in nem sehr frühen Alpha-Stadium.
Wer sich dafür interessiert, morgen oder so sollte es fertig werden, gibts dann auf meiner hp zum download mit quellcode.

Socke

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

2

01.01.2008, 17:03

Der Fehler tritt deshalb am Ende auf, weil da die Objekte aus dem Gültigkeitsereich zerstört werden. Interessant sind also die Destruktoren bzw. die Variablen aus der Instanz. Schau mal was passiert, wenn du alles bis auf die Variable auskommentierst. Dann holst du nach und nach den Code wieder rein, damit du siehst wodurch der Fehler wirklich ausgelöst wird.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Faule Socke

Community-Fossil

  • »Faule Socke« ist der Autor dieses Themas

Beiträge: 1 915

Wohnort: Schreibtischstuhl

  • Private Nachricht senden

3

01.01.2008, 19:41

Ich werde das Programm vorher nochmal komplett überarbeiten, da noch viel alter code drin ist. Ich hoffe das hilft, ansonsten werde ich natürlich deinem ratschlag folge leisten(geiler satzbau^^).

Socke

4

01.01.2008, 23:30

Tjo und sonst mal Breakpoint vor und nach Konstruktor aufruf und vor verlassen der Funktion setzen und mal kontrollieren was für werte in IP stehen ...
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

Faule Socke

Community-Fossil

  • »Faule Socke« ist der Autor dieses Themas

Beiträge: 1 915

Wohnort: Schreibtischstuhl

  • Private Nachricht senden

5

02.01.2008, 13:52

Hi,

Das problem ist bei einem anderen projekt nun auch aufgetreten, also hab ich es so gemacht, wie du gesagt hattest. Erst dachte ich, das problem läge an meiner socketklasse, habe also alle variablen und den ganzen funktionscode auskommentiert.
Dann erst die konsolenklasse wieder reingenommen. ging. dann die ip klasse reingenommen zack ging net mehr. also debuggt und einen eventuellen fehler im konstruktor behoben(hier wurde ein anderer konstruktor aufgerufen). dann ging es. bis zum ende vom programm. da der destruktor aber leer ist, wundert es mich, warum es daran abstürtzt.

Ich hoffe ihr könnt mir diesmal helfen, hier meine IP-klasse:
nsAddress.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace NetStream
{
    /*!
    This is a class for IP-Addresses.
    */
    class NETSTREAM_API CIP
    {
    public:
        // --- Constructors ---------------------

        CIP();
        CIP(const std::string &IP);
        CIP(const char *pcIP);
        CIP(const CIP &pSrc);
        ~CIP();

        // --- Basic-Methods --------------------

        void    SetH(const std::string &IP);
        void    SetN(const unsigned long ulAddr);

        std::string     GetH() const;
        unsigned long   GetN() const;

        // --- Operators ------------------------

        unsigned char   &operator [] (unsigned char ucIndex);
        const bool      operator == (const CIP &Right) const;
        const bool      operator != (const CIP &Right) const;

    private:
        // --- Variables ------------------------

        unsigned char   m_ucAddr[4];
    };
}


Hier die implementation der methoden:
nsAddress.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
namespace NetStream
{
    CIP::CIP()
    {
        //! Default constructor.

        SetH("0.0.0.0");
    }

    CIP::CIP(const std::string &IP)
    {
        //! Initialising constructor.

        //! \param[in] IP the IP-Address.

        SetH(IP);
    }

    CIP::CIP(const char *pcIP)
    {
        //! Initialising constructor.

        //! \param[in] pcIP The IP-Address.

        SetH(pcIP);
    }

    CIP::CIP(const CIP &pSrc)
    {
        //! Copy constructor.

        //! \param[in] pSrc Reference to the Source object.

        m_ucAddr[0] =   pSrc.m_ucAddr[0];
        m_ucAddr[1] =   pSrc.m_ucAddr[1];
        m_ucAddr[2] =   pSrc.m_ucAddr[2];
        m_ucAddr[3] =   pSrc.m_ucAddr[3];
    }

    CIP::~CIP()
    {
        //! Destructor.

    }

// =================================================================================================

// Basic-Methods


    void CIP::SetH(const std::string &IP)
    {
        //! Sets the IP-Address with an IP-String.

        //! \param[in] IP The IP String.

        if(sscanf_s(IP.c_str(), "%d.%d.%d.%d", &m_ucAddr[0], &m_ucAddr[1], &m_ucAddr[2], &m_ucAddr[3]) == -1)
            throw(std::bad_exception("Can not create IP-Address from String."));
    }

    void CIP::SetN(const unsigned long ulAddr)
    {
        //! Sets the IP-Address with an Network-Ordered Address.

        //! \param[in] ulAddr The Address.

        char    acBuffer[32];
        in_addr Addr;
        Addr.S_un.S_addr    =   ulAddr;
        strcpy_s(acBuffer, 32, inet_ntoa(Addr));
        SetH(acBuffer);
    }

    std::string CIP::GetH() const
    {
        //! Returns the Address in Host-Byte-Order.

        //! \return The IP-String.

        std::string Buffer;
        char        acBuffer[32];
        Buffer.clear();
        /*_itoa_s(static_cast<signed>(m_ucAddr[0]), acBuffer, 32);  Buffer  +=  acBuffer;   Buffer  +=  ".";
        _itoa_s(static_cast<signed>(m_ucAddr[1]), acBuffer, 32);    Buffer  +=  acBuffer;   Buffer  +=  ".";
        _itoa_s(static_cast<signed>(m_ucAddr[2]), acBuffer, 32);    Buffer  +=  acBuffer;   Buffer  +=  ".";
        _itoa_s(static_cast<signed>(m_ucAddr[3]), acBuffer, 32);    Buffer  +=  acBuffer;
        Buffer  +=  static_cast<signed>(m_ucAddr[0]);   Buffer  +=  ".";
        Buffer  +=  static_cast<signed>(m_ucAddr[1]);   Buffer  +=  ".";
        Buffer  +=  static_cast<signed>(m_ucAddr[2]);   Buffer  +=  ".";
        Buffer  +=  static_cast<signed>(m_ucAddr[3]);*/
        sprintf_s(acBuffer, "%d.%d.%d.%d", &m_ucAddr[0], &m_ucAddr[1], &m_ucAddr[2], &m_ucAddr[3]);
        return Buffer;
    }

    unsigned long CIP::GetN() const
    {
        // Returns the Address in Network-Byte-Order.

        // \return The IP-Address.

        return inet_addr(GetH().c_str());
    }

// =================================================================================================

// Operators


    unsigned char &CIP::operator [] (unsigned char ucIndex)
    {
        //! Returns one Byte of the Address.

        assert(ucIndex < 4);
        return m_ucAddr[ucIndex];
    }

    const bool CIP::operator == (const CIP &Right) const
    {
        for(unsigned i = 0; i < 4; i++)
        {
            if(m_ucAddr[i] != Right.m_ucAddr[i])    return false;
        }

        return true;
    }

    const bool CIP::operator != (const CIP &Right) const
    {
        for(unsigned i = 0; i < 4; i++)
        {
            if(m_ucAddr[i] != Right.m_ucAddr[i])    return true;
        }

        return false;
    }
}


Sry falls das jetzt etwas viel ist, aber ich denke das meiste sind kommentare.
Zur Funktion CIP::GetH muss ich auch noch etwas sagen: Ich hab lange probiert, jedoch haben beide methoden, die nun auskommentiert sind, nicht richtig funktioniert(beide haben müll ausgespuckt). Die methode die ich jetzt verwende funktioniert hoffentlich besser.

Socke

6

02.01.2008, 14:42

Also ich greif jetzt mal einzellne Stellen raus, die du verändern solltest:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
std::string CIP::GetH() const
{
    std::string Buffer;
    char        acBuffer[32];
    Buffer.clear(); 
    sprintf_s(acBuffer, "%d.%d.%d.%d", &m_ucAddr[0], &m_ucAddr[1], &m_ucAddr[2], &m_ucAddr[3]);
        return Buffer;
}
...
Hmm scheinbar hast du den Überblick über die Funktion verloren ;)
Also erstmal alle Kommentare da raus nehmen!
%d steht für signed integers (http://www.cppreference.com/stdio/printf.html). Du übergibst einen Zeiger auf eine unsignierte Ganzzahl.
&arr[0] == (fast) arr
arr[0] == (fast) *arr

Dann füllst du deinen Buffer acBuffer, aber nicht deinen String Buffer. Warum du clear aufrufst ist mir auch nicht ganz klar, (http://www.cplusplus.com/reference/string/string/clear.html) denn der String ist solange leer, bis du was rein tust ;)

C-/C++-Quelltext

1
2
3
4
5
6
std::string CIP::GetH() const
{
    char arr_buff[32];
    std::sprintf(arr_buff, "%u.%u.%u.%u", m_ucAddr[0], m_ucAddr[1], m_ucAddr[2], m_ucAddr[3]);
    return std::string(arr_buff);
}
tut am ehesten das, was du willst.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
const bool CIP::operator == (CIP const& rhs) const
{
    for (unsigned char i(0); i < 4; ++i)
        if (m_ucAddr[i] != rhs.m_ucAddr[i]) return false;
    
    return true;
}

const bool CIP::operator != (CIP const & rhs) const
{ return !(*this == rhs); }
Einen von beiden zu implementieren reicht hier. Wobei es die Frage ist, ob da eine Schleife wirklich notwendig ist, oder pure Faulheit :D

C-/C++-Quelltext

1
2
3
4
5
CIP::CIP()
    {
        //! Default constructor.

        SetH("0.0.0.0");
    } 
ist in diesem Fall sicherlich unperformanter als ein einfaches:

C-/C++-Quelltext

1
2
3
4
CIP::CIP
{
    std::fill(m_ucAddr, m_ucAddr + 4, 0);
}
.

Dann solltest du vllt. dich für C++ oder C entscheiden und nicht auf C-Relikte aufbauen.

C-/C++-Quelltext

1
2
3
4
5
6
7
void CIP::SetH(const std::string &IP)
    {
        //! Sets the IP-Address with an IP-String.

        //! \param[in] IP The IP String.

        if(sscanf_s(IP.c_str(), "%d.%d.%d.%d", &m_ucAddr[0], &m_ucAddr[1], &m_ucAddr[2], &m_ucAddr[3]) == -1)
            throw(std::bad_exception("Can not create IP-Address from String."));
    } 
. Auch hier ist es eine unsignierte Ganzzahl! Wobei ein Test auf -1 nicht ganz erklärlich ist. Ein Test auf < 4 wäre doch sinnvoller, da sscanf zurück gibt, wie viele Werte gelesen werden konnten!

C-/C++-Quelltext

1
2
3
4
void CIP::SetH(std::string const& str)
{
    if (std::sscanf(str.c_str(), "%u.%u.%u.%u", &m_ucAddr[0], &m_ucAddr[1], &m_ucAddr[2], &m_ucAddr[3]) < 4) throw std::invalid_argument("invalid string");
}
Doch C++-like wären mal wieder Streams oder sich boost anzugucken ;)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
void CIP::SetH(std::string const& str)
{
    std::istringstream ss(str);
    char seperator;
    for (unsigned char i(0); i < 4; ++i)
    {
        ss >> m_ucAddr[i];
        ss >> seperator;
        if (!ss || seperator != '.') throw std::invalid_argument("invalid string");
    }
}
. Das kann man noch verfeinern, aber sollte so in etwa aussehen.


Dann dein Kopierkonstruktor könntest du auf folgendes Reduzieren:

C-/C++-Quelltext

1
2
3
4
CIP::CIP(CIP const & rhs)
{
    std::memcpy(m_ucAddr, pSrc.m_ucAddr, 4 * sizeof (unsigned char));
}
. Oder std::copy geht auch, wobei für POD auch ein einfaches std::memcpy reicht!

Was du in SetN macht, solltest du vllt. mal kurz erklären!

Sonst sollte das so alles stimmen und der Fehler wo anders liegen ;)
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

7

02.01.2008, 15:41

Schmeiß mal lieber aller Buffer raus und ersetz sie durch stringstreams oder einfach strings. Das sollte dein Problem lösen, weil der Fehler meist bei Zeiger"hexerei" auftritt.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

8

02.01.2008, 16:16

@nox: na guck mal was ich ihm immer verbessert habe ...
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

9

02.01.2008, 16:53

Ja für die SetH Methode. Aber er nutzt ja noch an einigen anderen Stellen Arrays.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Faule Socke

Community-Fossil

  • »Faule Socke« ist der Autor dieses Themas

Beiträge: 1 915

Wohnort: Schreibtischstuhl

  • Private Nachricht senden

10

02.01.2008, 17:02

Zitat von »"Deviloper"«


Dann füllst du deinen Buffer acBuffer, aber nicht deinen String Buffer. Warum du clear aufrufst ist mir auch nicht ganz klar, (http://www.cplusplus.com/reference/string/string/clear.html) denn der String ist solange leer, bis du was rein tust ;)

Ja das mit dem Puffer und mti clear hab ich direkt nach dem posten gemerkt auch schon gefixt. Deine lösung ist trotzdem noch nen ticken effizienter. Eig. will ich hier sowieso stringstreams verwenden, aber die mögen mich nicht.

Zitat von »"Deviloper"«


Einen von beiden zu implementieren reicht hier. Wobei es die Frage ist, ob da eine Schleife wirklich notwendig ist, oder pure Faulheit :D

Ich implementiere grunsätzlich beide operatoren... hab auch lange überlegt, ob ich das in ner schleife mache oder nicht, ich glaube ohne wäre sogar schneller gegangen, beim anderen muss ich ja nur c&p machen.

Zitat von »"Deviloper"«


ist in diesem Fall sicherlich unperformanter als ein einfaches:

C-/C++-Quelltext

1
2
3
4
CIP::CIP
{
    std::fill(m_ucAddr, m_ucAddr + 4, 0);
}
.

Danke für den Tipp ;-)

Zitat von »"Deviloper"«


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
void CIP::SetH(std::string const& str)
{
    std::istringstream ss(str);
    char seperator;
    for (unsigned char i(0); i < 4; ++i)
    {
        ss >> m_ucAddr[i];
        ss >> seperator;
        if (!ss || seperator != '.') throw std::invalid_argument("invalid string");
    }
}
. Das kann man noch verfeinern, aber sollte so in etwa aussehen.

Das ist genau das was ich gebraucht habe... ich sollte mich wirklich mit stringstreams befassen, aber in meinen büchern steht nix dazu und msdn ist da auch sehr mager wie ich finde.


Zitat von »"Deviloper"«


Dann dein Kopierkonstruktor könntest du auf folgendes Reduzieren:

C-/C++-Quelltext

1
2
3
4
CIP::CIP(CIP const & rhs)
{
    std::memcpy(m_ucAddr, pSrc.m_ucAddr, 4 * sizeof (unsigned char));
}
. Oder std::copy geht auch, wobei für POD auch ein einfaches std::memcpy reicht!


Zitat von »"Deviloper"«


Was du in SetN macht, solltest du vllt. mal kurz erklären!

Also mit SetN kann man die Ip in Network-byte-order eingeben. Deshalb muss sie zuerst und host-byte-order umgewandelt werden und dann wird sie mit SetH gesetzt.

Zitat von »"Deviloper"«


Sonst sollte das so alles stimmen und der Fehler wo anders liegen
;)


Meinst du?

Sry das die antwort erst so spät kommt aber meine mutter hat beim aufräumen den router ausgesteckt...

Werbeanzeige