Fehler bei übergabe von const char*

FBIagent

Erfahrenes Mitglied
System: Win XP Pro x64
IDE: MSVC 2005 Pro

Wenn ich irgendwelche Informationen, die der Problemlösung helfen sollten, vergessen habe, sagt mir bitte bescheid.

Vorab:
Ich bekomme neuerdings immer einen schönen Freeze, wenn ich debuggen will.

Folgendes Problem:
Ich habe mir eine klein StringKlasse geschrieben. Diese hat eine Methode 'append'
und dazu 3 mal den Oprator '+='. Von diesen wird 'append' aufgerufen.
Das Problem ist, dass ich einen Absturz verzeichne, wenn ich mysql_error(&_connection)
an den String anhängen mochte. Der Rückgabewert ist const char *. Ich habe bereits versucht einen const char * zu deklarieren, diesem einen beliebigem Wert zugewiesen.
Dies hat funktioniert auch ohne Probleme.

Ein Problem mit mysql_error() ist es nicht da ich dies auch schon mit std::string
versucht habe und es ausgegeben habe.

String.h
C++:
/* 
 * String.h - string class usable with/without null terminated c strings
 *
 * Author: Christian
 * Created: June 14, 2007
 * Last Modified: June 15, 2007
 *
 */

#ifndef __VALOTUNARIER_STRING_H__
#define __VALOTUNARIER_STRING_H__

#include "ValotunarierMacros.h"

namespace Valotunarier
{
    class VALOTUNARIER_API String
    {
    public:
        String();
        String(const String &str);
        String(const char *str, unsigned int len);
        /* only for null terminated c strings */
        String(const char *str);
        String(const char &ch);
        virtual ~String();

        void set(const char *str, unsigned int len);
        void append(const char *str, unsigned int len);
        void replace(unsigned int index, unsigned int len, const String &str);
        void replace(unsigned int index, unsigned int len, const char *str, unsigned int strLen);
        /* only for null terminated c strings */
        void replace(unsigned int index, unsigned int len, const char *str);
        void makeEmpty();
        const int find(const char &ch);

        bool isEquals(const char *str, unsigned int len);

        const unsigned int &getLength() const;
        /* returns the string without extra null termination(no copy) */
        const char *get() const;
        /* returns a copy of the string without extra null termination */
        char *getCopy() const;
        /* returns the string with extra null termination(no copy) */
        const char *getNullTerminated() const;
        /* returns a copy of the string with extra null termination */
        char *getNullTerminatedCopy() const;

        const String &operator+=(const String &str);
        /* only for null terminated c strings */
        const String &operator+=(const char *str);
        const String &operator+=(const char &ch);

        const String &operator=(const String &str);
        /* only for null terminated c strings */
        const String &operator=(const char *str);
        const String &operator=(const char &ch);

        const bool operator==(const String &str);
        /* only for null terminated c strings */
        const bool operator==(const char *str);
        const bool operator==(const char &ch);

        char &operator[](unsigned int index);
    private:
        char *_str;
        char *_strNullTerminated;
        unsigned int _len;
    };
}

#endif

String.cpp
C++:
#include <windows.h>

#include <string>

#include "..\include\String.h"

namespace Valotunarier
{
    String::String()
    : _str(NULL), _strNullTerminated(NULL), _len(0)
    {}

    String::String(const String &str)
    {
        set(str.get(), str.getLength());
    }

    String::String(const char *str, unsigned int len)
    {
        set(str, len);
    }

    String::String(const char *str)
    {
        set(str, strlen(str));
    }

    String::String(const char &ch)
    {
        char *str = new char[1];

        str[0] = ch;
        set(str, 1);
        delete[] str;
    }

    String::~String()
    {
        if (_str != NULL)
            delete[] _str;

        if (_strNullTerminated != NULL)
            delete[] _strNullTerminated;
    }

    void String::set(const char *str, unsigned int len)
    {
        makeEmpty();

        if (len == 0)
            return;

        _str = new char[len];
        _strNullTerminated = new char[len+1];

        for (unsigned int i=0;i<len;i++)
        {
            _str[i] = str[i];
            _strNullTerminated[i] = str[i];
        }

        _strNullTerminated[len] = '\0';
        _len = len;
    }

    void String::append(const char *str, unsigned int len)
    {
        if (len == 0)
            return;

        unsigned int newLen = _len+len;
        char *tempStr = new char[newLen];
        char *tempStrNullTerminated = new char[newLen+1];

        for (unsigned int i=0;i<newLen;i++)
        {
            if (i < _len)
            {
                tempStr[i] = _str[i];
                tempStrNullTerminated[i] = _str[i];
            }
            else
            {
                tempStr[i] = str[i-_len];
                tempStrNullTerminated[i] = str[i-_len];
            }
        }

        tempStrNullTerminated[newLen] = '\0';
        makeEmpty();
        _str = tempStr;
        _strNullTerminated = tempStrNullTerminated;
        _len = newLen;
    }

    void String::replace(unsigned int index, unsigned int len, const String &str)
    {
        replace(index, len, str.get(), str.getLength());
    }

    void String::replace(unsigned int index, unsigned int len, const char *str, unsigned int strLen)
    {
        if (len == 0 || strLen == 0)
            return;

        unsigned int newLen = _len-len+strLen;
        char *tempStr = new char[newLen];
        char *tempStrNullTerminated = new char[newLen+1];
        unsigned int i = 0;

        for (;i<index;i++)
        {
            tempStr[i] = _str[i];
            tempStrNullTerminated[i] = _str[i];
        }

        for (i=0;i<strLen;i++)
        {
            tempStr[i+index] = str[i];
            tempStrNullTerminated[i+index] = str[i];
        }

        for (i=0;i<_len-index-len;i++)
        {
            tempStr[i+index+strLen] = _str[i+index+len];
            tempStrNullTerminated[i+index+strLen] = _str[i+index+len];
        }

        tempStrNullTerminated[newLen] = '\0';
        makeEmpty();
        _str = tempStr;
        _strNullTerminated = tempStrNullTerminated;
        _len = newLen;
    }

    void String::replace(unsigned int index, unsigned int len, const char *str)
    {
        replace(index, len, str, strlen(str));
    }

    void String::makeEmpty()
    {
        if (_str != NULL)
        {
            delete[] _str;
            _str = NULL;
        }

        if (_strNullTerminated != NULL)
        {
            delete[] _strNullTerminated;
            _strNullTerminated = NULL;
        }

        _len = 0;
    }

    const int String::find(const char &ch)
    {
        for (unsigned int i=0;i<_len;i++)
        {
            if (_str[i] == ch)
                return i;
        }

        return -1;
    }
    
    bool String::isEquals(const char *str, unsigned int len)
    {
        if (_len != len)
            return false;

        for (unsigned int i=0;i<_len;i++)
        {
            if (_str[i] != str[i])
                return false;
        }

        return true;
    }

    const unsigned int &String::getLength() const
    {
        return _len;
    }

    const char *String::get() const
    {
        return _str;
    }

    char *String::getCopy() const
    {
        char *retStr = new char[_len];

        for (unsigned int i=0;i<_len;i++)
            retStr[i] = _str[i];

        return retStr;
    }

    const char *String::getNullTerminated() const
    {
        return _strNullTerminated;
    }

    char *String::getNullTerminatedCopy() const
    {
        char *retStr = new char[_len+1];

        for (unsigned int i=0;i<_len+1;i++)
            retStr[i] = _strNullTerminated[i];

        return retStr;
    }

    const String &String::operator+=(const String &str)
    {
        append(str.get(), str.getLength());
        return *this;
    }

    const String &String::operator+=(const char *str)
    {
        append(str, strlen(str));
        return *this;
    }

    const String &String::operator+=(const char &ch)
    {
        char *str = new char[1];

        str[0] = ch;
        append(str, 1);
        delete[] str;
        return *this;
    }

    const String &String::operator=(const String &str)
    {
        set(str.get(), str.getLength());
        return *this;
    }

    const String &String::operator=(const char *str)
    {
        set(str, strlen(str));
        return *this;
    }

    const String &String::operator=(const char &ch)
    {
        char *str = new char[1];

        str[0] = ch;
        set(str, 1);
        delete[] str;
        return *this;
    }

    const bool String::operator==(const String &str)
    {
        return isEquals(str.get(), str.getLength());
    }
 
    const bool String::operator==(const char *str)
    {
        return isEquals(str, strlen(str));
    }
    
    const bool String::operator==(const char &ch)
    {
        char *str = new char[1];

        str[0] = ch;

        bool ret = isEquals(str, 1);

        delete[] str;
        return ret;
    }
    
    char &String::operator[](unsigned int index)
    {
        return _str[index];
    }
}

Wo der Fehler auftritt:
C++:
        if (mysql_query(&_connection, statement.getQuery().getNullTerminated()) > 0)
        {
            const char *testStr = "blub";

            _isConnected = false;
            String msg = "Sql Exception: ";
            //msg += mysql_error(&_connection); <-- funktioniert nicht
            msg += testStr; // <-- funktioniert
            msg += "(";
            msg += _name;
            msg += ")";
            throw MException(msg);
        }

Es wäre net wenn mir jemand hilft oder besser gesagt nur erklärt warum das eine const char * anhängen nicht funktioniert und das andere
dann wieder doch.

Best wishes
FBIagent
 
Zuletzt bearbeitet von einem Moderator:
Hallo auch,
was für einen Ergebnistyp gibt denn mysql_query zurück? Welche Argument-Typen erwartet es?

int mysql_query(MYSQL *mysql, const char *query)

MYSQL ist die struktur der MYSQL C API für die Server verbindung.

-----------

Hat aber nichts mit meinem Problem zu tun. Das Problem liegt bei
msg += mysql_error(&_connection);

Wie schon gesagt resultiert aud mysql_error() ein const char*.
Es muss an meiner StringKlasse liegen da dies mit std::string funktioniert,
ich kann mir aber nicht erklären warum.

Best wishes
FBIagent
 
Hi.

Also ich kann eigentlich keinen Fehler in der append Methode entdecken. (Kann natürlich auch sein, dass ich ihn einfach nicht sehe ;))

Am besten wäre es du würdest einen Testfall finden, so dass man den Fehler nachvollziehen kann.

Wenn dein Debugger nicht funktioniert, dann probier's doch mal mit dem "poor-man's debugger" - sprich: lass dir in der append Funktion einige Variablen auf der Standarderrorausgabe ausgeben oder versuch einen anderen Compiler/Debugger.

Gruß
 
So ich habe noch ein paar Tests durchgeführt. Mir ist etwas aufgefallen. Dazu aber erstmal
die Grundlage zu dem was ich denke:
Ich habe eine Solution mit 2 Hauptprojekten, "core" und "core_sql". Beides DLL Projekte.
"core" beinhaltet die StringKlasse. "core_sql" linkt die DLL von "core".
So nun ist in dieser Solution noch ein Testprojekt namens "StringClassTest". Dieses
Projekt linkt die DLL von "core". Dort habe ich keine Probleme mit dem append. In einem
weiteren Testprojekt namens "SqlTest" linke ich die DLL von "core" und "core_sql".

Kann es sein das es daran liegt, dass "core_sql" die Definition von String garnicht mehr
kennt beim Kompilieren von "SqlTest"? Ich meine String ist ja nur exportiert in "core",
ich linke zwar "core" vor "core_sql", "core_sql" hat auch zugriff auf den StringKlassen
header, aber nicht auf den Source. Kann das zu meinem Problem führen?

Best wishes
FBIagent
 
Also ich muss sagen, ich komme im Momment auf keinen grünen Zweig. Ich finde auch
keine Informationen zu meiner Theorie im vorherigen Post. Nur sicher ist: Importiert aus der
DLL funktioniert is aus irgendeinem Grund nicht. Vieleicht mache ich irgendwo einen
Fehler beim exportieren.

Die Werte der Variablen in "append" scheinen alle richtig zu sein.

Best wishes
FBIagent
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück