PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : problem mit funktion



Tuxist
17-05-2007, 13:19
cgiconvert.cpp


#include <iostream>
#include <string>
#include <fstream>

#include "include/libhtml++.h"

string cgi::convert(const string formname)
{
const char* query;
string query1;
query1 = query;
int start;
int end;

start = query1.find(formname);
start +1;

if (query1.find("&", start) !=string::npos )
{
end = query1.rfind(formname, end);
}
else
{
end = query1.find("&", start);
}
query1.substr(start,end);
};

libhtml.h


#include <iostream>
#include <string>
#include <sstream>

using namespace std;

class cgi
{
public:
const char* value;
const char* query;
char *puffer;
const string formname;
string *anfrage();
string convert(const string formname);
string formselectoutput;
string methodform;
};

class htmlformsubmit : public cgi
{
private:
string submitname;
string methodform;
void inputsubmit( string submitname);
public:
htmlformsubmit(string submitname)
{
inputsubmit(submitname);
*anfrage();
};

};

class htmlformselect : public cgi
{
private:
string formselectname;
string formselectinput;
void formselectdisplay(string formselectname, string formselectinput, string methodform);
public:
htmlformselect(string formselectname, string formselectinput, string methodform)
{
formselectdisplay (formselectname, formselectinput, methodform);
};

};


tuxlibcss.cpp:


void libcss::libcssout()
{
string cssstyle;
cssstyle = cgi::convert("cssstyle");
cout << "<link rel=\"stylesheet\" type=\"text/css\" href=\"" << folder << cssstyle << ".css" << "\">" << endl;
};


gcc out libcss:


g++ -c -fpic -Wall -L/usr/lib/ -I/usr/include css.cpp
css.cpp:40:3: warning: no newline at end of file
css.cpp: In member function »void libcss::libcssout()«:
css.cpp:38: Fehler: Elementfunktion »std::string cgi::convert(std::string)« kann nicht ohne Objekt aufgerufen werden
make: *** [all] Fehler 1


program download
ftp://tuxist.de/tuxist/tuxcmslib.tar.gz
ftp://tuxist.de/tuxist/cgi-bin.tar.gz

bischi
17-05-2007, 13:58
Und was genau ist das Problem?

MFG Bischi

PS: Also einfach "nur" ein Kompilierfehler?

anda_skoa
17-05-2007, 14:08
Die Fehlermeldung sagt ja ansich eh schon, wo das Problem ist.
Du rufst cgi::convert() auf, ohne eine Objektinstanz der Klasse cgi zu haben.

Aber mir sind da noch ein paar Sachen aufgefallen


cgiconvert.cpp


string cgi::convert(const string formname)
{
const char* query;
string query1;
query1 = query;


"query1" bekommt eine Zuweisung aus einer nicht initialisierten Variable "query", das willst du sicher nicht





int start;
int end;

start = query1.find(formname);
start +1;


Die letzte Zeile hat keine Auswirkung, weil das Ergebnis der Addition nicht benutzt wird. Ich denke du willst


++start;
// oder
start++;
// oder
start += 1;






if (query1.find("&", start) !=string::npos )
{
end = query1.rfind(formname, end);
}
else
{
end = query1.find("&", start);


wenn das "if" oben false wird, wird ein zweiter Aufruf des selben "find()" vermutlich wieder das selbe Ergebnis geben :)





class cgi
{
public:
const char* value;
const char* query;


In der Methode "convert()" hast du eine lokale Variable mit gleichen Namen. Ich hoffe dir ist klar, wo dann welcher Wert Gültigkeit hat.





const string formname;
string *anfrage();
string convert(const string formname);


Variablenname "formname" ist gleich dem Parameternamen von "convert()", siehe oben.
Nachdem bei der Membervariable auch noch ein const steht, aber kein Konstruktor existiert, der ihr einen Wert zuweist, ist vermutlich dieses Vorkommnis des Namens falsch.

Das "string*" als Rückgabewert von "anfrage()" sieht auch komisch aus.





class htmlformsubmit : public cgi
{
private:
string submitname;
string methodform;
void inputsubmit( string submitname);


"submitname", siehe oben.





class htmlformselect : public cgi
{
private:
string formselectname;
string formselectinput;
void formselectdisplay(string formselectname, string formselectinput, string methodform);
public:
htmlformselect(string formselectname, string formselectinput, string methodform)
{
formselectdisplay (formselectname, formselectinput, methodform);
};


"formselectname", "formselectinput", siehe oben.

Ciao,
_

Tuxist
19-05-2007, 15:13
Habe jetzt einiges abgeändert jezt habe probleme beim auführen des programm ausgabe :


jan@dibsi:~/tuxist.de/tuxcms/cgi-bin$ ./index.cgi
Content-Type:text/html


<html>
<head>
<title>tuxist.de</title>
</head>
<body>
<form action="index.cgi" method=GET> <select name=" cssstyle" ><option>default</option><option>black</option><option>..</option><option>.</option>> </form>
</select><Input Type="submit" value="Switch Design">
Segmentation fault (core dumped)


gdb ausgabe:


(gdb) bt
#0 0x00002ae4f6c591c0 in cgi::anfrage () from /usr/lib/tuxcms/libhtml++.so
#1 0x00002ae4f6e5bcdf in htmlformsubmit::htmlformsubmit ()
from /usr/lib/tuxcms/libcss.so
#2 0x00002ae4f6e5b772 in libcss::libcssread () from /usr/lib/tuxcms/libcss.so
#3 0x0000000000400e4b in libcss::libcss ()
#4 0x0000000000400d4b in main ()
(gdb)


cgi.cpp


#include <iostream>
#include <string>
#include <fstream>
#include "include/libhtml++.h"

using namespace std;

string *cgi::anfrage()
{
*puffer = NULL;
char *request = getenv("REQUEST_METHOD");

if(NULL == request )
{
return NULL;
}

else if( strcmp(request, "GET") == 0 )
{
query = getenv("QUERY_STRING");

if( NULL == query )
{
return NULL;
}

}


else if ( strcmp(request, "POST") == 0 )
{
query = (getenv("CONTENT_LENGTH"));
}


else //bei Fehler oder keiner eingabe

return NULL;
}

string cgi::out(string formname)
{
if(query == NULL )
{
return NULL;
}

else

query1 = query;
int start;
int end;

start = query1.find(formname);
start += 1;

if (query1.find("&", start) !=string::npos )
{
end = query1.rfind(formname, end);
}
else
{
end = query1.find("&", start);
}
formname.substr(start,end);
}

string cgi::getcgi(string formname)
{
anfrage();
out(formname);
return (formname);
}




#include <iostream>
#include <string>
#include <sstream>

using namespace std;

class cgi
{
private:
string query1;

public:
const char* value;
const char* query;
char *puffer;
string *anfrage();
string out(string formname);
string getcgi(string formname);
};



class htmlformsubmit : public cgi
{
private:
string submitname;
string methodform;
void inputsubmit( string submitname);
public:
htmlformsubmit(string submitname)
{
inputsubmit(submitname);
*anfrage();
};

};

class htmlformselect : public cgi
{
private:
void formselectdisplay(string formselectname, string formselectinput, string methodform);
public:
htmlformselect(string formselectname, string formselectinput, string methodform)
{
formselectdisplay (formselectname, formselectinput, methodform);
};

};


quellcode neu hochgeladen

anda_skoa
25-05-2007, 15:44
Du hast nicht in allen Zweigen von cfgi::abfrage() ein entsprechendes "return".

Sollte ansich in den Kompilerwarnings vorgekommen sein.
Bist du sicher, daß du "-Wall" als Compileroption gesetzt hast?

Ciao,
_

Tuxist
03-06-2007, 13:19
Habe mal kräftig aufgeräumt leider läuft programm immer noch nicht richtig:
cgi.cpp


#include <iostream>
#include <string>
#include <fstream>
#include "include/libhtml++.h"

using namespace std;

char *cgi::anfrage(char *formname)
{

char *request = getenv("REQUEST_METHOD");

if( NULL == request )
{
return NULL;
}

else if( strcmp(request, "GET") == 0 )
{
query = getenv("QUERY_STRING");
}

if( query == "0")
{
return NULL;
}

int start;
int end;

start = query.find(formname);
if (query.find(formname) !=string::npos )
{
return NULL;
}

start += 1;

if (query.find("&", start) !=string::npos )

{
end = query.rfind(formname, end);
}
else
{
end = query.find("&", start);
end -= 1;
}


query.substr(start,end);
query.copy(formname,string::npos);
return (formname);

}


libhtml++.h


#include <iostream>
#include <string>
#include <sstream>

using namespace std;

class cgi
{
private:
string query;
public:
char *anfrage(char *formname);
};



class htmlformsubmit
{
private:
void inputsubmit( string submitname);
public:
htmlformsubmit(string submitname)
{
inputsubmit(submitname);
};

};

class htmlformselect
{
private:
void formselectdisplay(string formselectname, string formselectinput, string methodform);
public:
htmlformselect(string formselectname, string formselectinput, string methodform)
{
formselectdisplay (formselectname, formselectinput, methodform);
};

};


css.cpp


#include <string>
#include "include/css.h"
#include <tuxcms/libhtml++.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>

using namespace std;


void libcss::libcssread()
{
folder = "style";
n = scandir(folder, &namelist, 0 , alphasort);
if (n < 0)
perror("No style folder");
else {
while(n--){
folders +=( "<option>");
folders +=( namelist[n]->d_name);
folders +=( "</option>");
delete(namelist[n]);
}
htmlformselect::htmlformselect("cssstyle", folders , "GET");
htmlformsubmit::htmlformsubmit("Switch Design");
}

delete(namelist);
}

void libcss::libcssout()
{
cgi css;
string cssstyle;
cssstyle = css.cgi::anfrage("cssstyle");

cout << "<link rel=\"stylesheet\" type=\"text/css\" href=\"" << folder << "/" << cssstyle << "/"<< "main.css" << "\">" << endl;
};


programmausgabe:


Starting program: /home/jan/tuxist.de/tuxcms/cgi-bin/index.cgi
Content-Type:text/html


<html>
<head>
<title>tuxist.de</title>
</head>
<body>
<form action="index.cgi" method=GET> <select name=" cssstyle" ><option>default</option><option>black</option><option>..</option><option>.</option>> </form>
</select><Input Type="submit" value="Switch Design">

Program received signal SIGSEGV, Segmentation fault.
0x00002acf1574c640 in strlen () from /lib/libc.so.6


backtrace:


(gdb) bt
#0 0x00002acf1574c640 in strlen () from /lib/libc.so.6
#1 0x00002acf14fe1d8c in std::string::operator= ()
from /usr/lib/libstdc++.so.6
#2 0x00002acf14d1918b in libcss::libcssout () from /usr/lib/tuxcms/libcss.so
#3 0x0000000000400e54 in libcss::libcss ()
#4 0x0000000000400d4b in main ()


Makefile


CXX=g++
CXXFLAGS= -c -fpic -L/usr/lib/ -I/usr/include -Iinclude -Wall -posix
CXXFLAGS1= -shared -o libhtml++.so

lib_SRC= \
htmlform.cpp \
cgi.cpp
lib_OBJS= \
htmlform.o \
cgi.o

all:
$(CXX) $(CXXFLAGS) $(lib_SRC)
$(CXX) $(CXXFLAGS1) $(lib_OBJS)

install:
mkdir -p /usr/lib/tuxcms/
mkdir -p /usr/include/tuxcms/
cp libhtml++.so /usr/lib/tuxcms/libhtml++.so
cp include/libhtml++.h /usr/include/tuxcms/libhtml++.h

remove:
rm /usr/lib/tuxcms/libhtml++.so
rm /usr/include/tuxcms/libhtml++.h

Tuxist
07-06-2007, 19:50
habe es gelöst mit return "error"; statt return NULL; zu verwenden

anda_skoa
08-06-2007, 14:04
Wenn du auf string als Rückgabewert umstellst, kannst du einfach einen leeren String zurückgeben.

Oder du hast eine string Referenz als Outputparameter und läßt den Rückgabewert mit einem bool der Indikator für "hat funktioniert" sein.

Im Grunde gibt es bei sowas immer drei Möglichkeiten:

1) Der Rückgabewert hat zusätzlich zum gütligen Wertebereich einen ungültigen Wert, zB mit einem Pointer, der im Falle von "ungültig" eben 0 ist


// wenn != 0, dann hat Aufruf funktioniert
string* funktion();


2) Der Rückgabewert inidziert den Erfolg, das Resultat geht über einen Referenzparameter


// wenn true, dann enthält result das Ergebnis, wenn false, dann ist result nicht näher definiert
bool funktion(string& result);


3) Der Rückgabewert ist das Resultat, ein zusätzlicher Parameter inidziert den Erfolg


// wenn ok == true, dann ist Rückgabewert weiterverwendbar
string funktion(bool& ok);

Diese Option wird oft verwendet, wenn der Check auf Erfolg nicht unbedingt notwendig ist. Dann wird dieser Parameter als optionaler Parameter mittels Pointer und Defaultwert gemacht


string funktion(bool* ok = 0);


Wenn die Möglichkeit besteht Exceptions zu benutzen, ist das natürlich die sauberste Lösung, allerdings muss man sich dafür ein bischen mit Exceptions und deren Handhabung auskennen.

Ciao,
_

Tuxist
16-06-2007, 15:38
cgi.cpp


#include <iostream>
#include <string>
#include <fstream>
#include "include/libhtml++.h"

using namespace std;

string cgi::anfrage()
{

char *request = getenv("REQUEST_METHOD");
char *env = getenv("QUERY_STRING");

if( request == 0)
{
return 0;
}

if (request == "GET")
{
if (env != 0)
{
query = env;
return query;
}

else
{
return 0;
}
}

else
return 0;

}


string cgi::output(char *formname)
{
anfrage();
if(&cgi::anfrage != NULL)
{
if (query.find(formname, start))
{
start += 1;
end = query.find("&", start);
end -= 1;
query.substr(start,end);
return query;
}

else
{
return 0;
}

}

else
return 0;

};


libhtml++.h


#include <iostream>
#include <string>
#include <sstream>

using namespace std;

class cgi
{
private:

int start;
int end;

public:
string query;
string anfrage();
string output(char *formname);
};


class htmlformsubmit
{
private:
void inputsubmit( string submitname);
public:
htmlformsubmit(string submitname)
{
inputsubmit(submitname);
};

};

class htmlformselect
{
private:
void formselectdisplay(string formselectname, string formselectinput, string methodform);
public:
htmlformselect(string formselectname, string formselectinput, string methodform)
{
formselectdisplay (formselectname, formselectinput, methodform);
};

};


css.cpp


#include <iostream>
#include <fstream>
#include <string>
#include "include/css.h"
#include <tuxcms/libhtml++.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>

using namespace std;


void libcss::libcssread()
{
folder = "style";
n = scandir(folder, &namelist, 0 , alphasort);
if (n < 0)
perror("No style folder");
else {
while(n--){
folders +=( "<option>");
folders +=( namelist[n]->d_name);
folders +=( "</option>");
delete(namelist[n]);
}
htmlformselect::htmlformselect("cssstyle", folders , "GET");
htmlformsubmit::htmlformsubmit("Switch Design");
}

delete(namelist);
}

void libcss::libcssout()
{
cgi css;
string cssstyle;
cssstyle = css.cgi::output("cssstyle");
if(&cssstyle != 0)
{
cout << "<link rel=\"stylesheet\" type=\"text/css\" href=\"" << folder << "/" << cssstyle<< "/"<< "main.css" << "\">" << endl;
}
else
{
cout << "<link rel=\"stylesheet\" type=\"text/css\" href=\"" << folder << "/" << "default" << "/"<< "main.css" << "\">" << endl;
}


};


habe das alles jetzt abgeändert bekomme jetzt leider als output


terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct NULL not valid
Aborted (core dumped)
jan@dibsi:~/tuxist.de/tuxcms/cgi-bin$


gdb bt:


#0 0x00002addb85b0ce5 in raise () from /lib/libc.so.6
#1 0x00002addb85b2660 in abort () from /lib/libc.so.6
#2 0x00002addb7ea9334 in __gnu_cxx::__verbose_terminate_handler ()
from /usr/lib/libstdc++.so.6
#3 0x00002addb7ea72c6 in ?? () from /usr/lib/libstdc++.so.6
#4 0x00002addb7ea72f3 in std::terminate () from /usr/lib/libstdc++.so.6
#5 0x00002addb7ea73da in __cxa_throw () from /usr/lib/libstdc++.so.6
#6 0x00002addb7e4309a in std::__throw_logic_error ()
from /usr/lib/libstdc++.so.6
#7 0x00002addb7e85449 in ?? () from /usr/lib/libstdc++.so.6
#8 0x00002addb7e855b2 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string () from /usr/lib/libstdc++.so.6
#9 0x00002addb79b7fea in cgi::anfrage () from /usr/lib/tuxcms/libhtml++.so
#10 0x00002addb79b810c in cgi::output () from /usr/lib/tuxcms/libhtml++.so
#11 0x00002addb7bba183 in libcss::libcssout () from /usr/lib/tuxcms/libcss.so
#12 0x0000000000400e54 in libcss::libcss ()
#13 0x0000000000400d4b in main ()

locus vivendi
16-06-2007, 16:54
Du darfst std::string nicht mit einem Nullzeiger konstruieren. Das tust du aber in cgi::anfrage z.B. durch die "return 0" Anweisungen.

Übrigens kannst du im Gdb mit "catch throw" auch einen Breakpoint setzen der nach dem Werfen einer Ausnahme ausgelöst wird. Mit dieser Vorkehrung musst du nicht erst warten bis der Ausnahmehandler aufgerufen wird um einen Backtrace einzuholen.
Zweitens, ein Backtrace mit Zeileninformationen ist tendenziell noch hilfreicher. Deshalb wäre es im Prinzip eine gute Idee, das Binary mit mit Debugging-Symbolen zu erzeugen.

anda_skoa
16-06-2007, 19:06
locus vivendi hat den Fehler ja schon aufgezeigt.

Wenn du einen Vorschlag zur Verbesserung aufgreifst, wäre es schön, wenn du nicht einfach nur ein paar Codezeilen exemplarisch änderst, sondern die Verbesserung als Gesamtes umsetzt.

D.h. wenn du den Rückgabewert änderst, solltest du auch die Stellen mit ändern, die den Rückgabewert erzeugen und die, die ihn verwenden.

Noch was anderes:



anfrage();

Da anfrage() einen Rückgabewert hat, sollte der vielleicht verwendet werden. Als Nebeneffekt der Funktion wird zwar auch die Variable query geändert, aber nur im Erfolgsfall, sonst hat sie den selben Wert wie zuvor.



if(&cgi::anfrage != NULL)

Die Adresse einer Method ist immer ungleich Null, sie muß ja irgendwo im Speicher sein, um vom Programm benutzt werden zu können.

Nachdem es anscheinend Schwierigkeiten gibt, die vorgeschlagen Verbesserungen mit deinem alten Code unter einen Hut zu bringen, versuch ich es mal ein bischen konkreter.



// Rückgabewert auch im Header auf bool ändern
bool cgi::anfrage()
{
query = string(); // Gespeicherten Wert zurücksetzen

char *request = getenv("REQUEST_METHOD");
char *env = getenv("QUERY_STRING");

if( request == 0)
{
return false; // Änderung des Rückgabewerts
}

if (request == "GET")
{
if (env != 0)
{
query = env;
return true; // Rückgabewert geändert
}
else
{
return false; // Rückgabewert geändert
}
}
else
return false;
}

// Parametertyp auf sicheren C++ Typ geändert
// Rückgabetyp geändert
bool cgi::output(const string& formname)
{
if (anfrage())
{
if (query.find(formname, start))
{
start += 1;
end = query.find("&", start);
end -= 1;
query = query.substr(start,end); // Rückgabewert von substr wurde nicht benutzt, Aktion also umsonst

return true;
}
else
{
return false; // Rückgabewert geändert, hier war vorher sogar einer dieser Nullpointer Fehler
}
}
else
return false; // Rückgabewert geändert, hier war vorher sogar einer dieser Nullpointer Fehler
}


Es ist bei der Programmierung meistens eine gute Idee, Klassen alleine für sich zu testen, wo immer das möglich ist. Wenn man sie immer nur im Endprogramm mit testet, ist die Fehlersucher mehr Aufwand und Fehler können sogar durch andere Fehler versteckt werden.

Ciao,
_

Tuxist
17-06-2007, 20:43
Danke schon mal für hilfe.
Quasi so kann man diese integrieren:


cgi css;
string cssstyle;
if (css.cgi::output("cssstyle"))
{
cssstyle = css.cgi::query;
}
else
{
cssstyle = "default";
}

anda_skoa
17-06-2007, 21:40
Nein, ganz falsch.

output() ist eine normale Methode der Klasse cgi, wie du daher auf "::" kommst, ist mir nicht erklärlich.

Selbes gilt natürlich auch für den Zugriff auf die Instanzvariable query.

C++ Basics:

Normale Methode (Methode eines Objekts, bzw. einer Instanz einer Klasse)


class Foo
{
public:
bool bar() { return true; }
};

Foo fooObject; // Object erzeugen.

if (fooObject.bar()) // Aufruf
{
// was auch immer
}


Statische Methode (Methode einer Klasse, ohne Objekt bzw. Instanz)


class Foo
{
public:
static bool bar() { return true; }
};

// Kein Objekt nötig

if (Foo::bar()) // Aufruf
{
// was auch immer
}


Variable eines Objekts, bzw. einer Instanz, auch Membervariable genannt


class Foo
{
public:
bool bar;
};

Foo fooObject; // Object erzeugen.

if (fooObject.bar) // Zugriff
{
// was auch immer
}


Statische Variable (Variable einer Klasse)


class Foo
{
public:
static bool bar;
};

// Definition in einem (nur einem) der CPP Dateien nötig
bool Foo::bar;

// Kein Objekt nötig

if (Foo::bar) // Zugriff
{
// was auch immer
}


Ciao,
_

Tuxist
24-06-2007, 15:19
Moin habe jetzt versucht alles umzusetzen. Bekomme leider aber keine ergebnis beim ausführen.


bool cgi::anfrage()
{
query = string();
char *request = getenv("REQUEST_METHOD");
char *env = getenv("QUERY_STRING");

if( request == NULL )
{
return false;
}

if (request == "GET")
{
if (env != 0 )
{
query = getenv("QUERY_STRING");
cout << query << end;
return true;
}

else
{
return false;
}
}

else
return false;
}


bool cgi::output(const string& formname)
{
if (anfrage())
{

if ( query.find(formname, start))
{
start += 1;
end = query.find("&", start);
if (end == 0)
{
end = query.size();
}
else
{
end -= 1;
}
query = query.substr(start,end);
return true;
}

else
{
return false;
}

}

else
return false;


teileabschnitt css.cpp


void libcss::libcssout()
{
cgi css;
string cssstyle;
if (css.output("cssstyle"))
{
cssstyle = css.query;
}
else
{
cssstyle = "default";
}

cout << "<link rel=\"stylesheet\" type=\"text/css\" href=\"" << folder << "/" << cssstyle << "/"<< "main.css" << "\">" << endl;
}

anda_skoa
27-06-2007, 15:40
Crashen tut es aber nicht mehr, oder?

Du kannst entweder mit einem Debugger schrittweise durch dein Programm gehen, oder an gezielten Stellen zB mit cerr Ausgaben machen, um festzustellen, wo es vorzeitig beendet.

Ciao,
_

Tuxist
27-06-2007, 17:30
crashen tut es nicht mehr.



if (request == "GET")
{
if (env != 0 )
{
query = getenv("QUERY_STRING");
cout << query << endl;
return true;
}


leider bekomme ich noch nicht mal hier eine ausgabe.

komplettes programm ftp://tuxist.de/tuxist/tuxcms.tar.gz