PDA

View Full Version : new problem with simple C++ static variables



landonmkelsey
17th August 2008, 01:30
I moved some stuff around in my TCP/IP program and now I get a duplicate defined
message for static variables.

The strange thing is that the compiler is calling the use of a static variable a definition. :confused:



#ifndef TCPIP_SERVER_H_
#define TCPIP_SERVER_H_
#include "ui_tcpip.h"
#include "inet.h"
#include <iostream>
#include <sstream>
#include <exception>
using namespace std;
#include "thread.cpp"
#include "sock_io.cpp"
#include "tstash.h"
#include <QtDebug>

typedef void* (*p_VOID_FUNCT)(void*);
class tcpip_server {

socklen_t clilen;
struct sockaddr_in cli_addr, serv_addr;
ushort port;
// struct sock_addr_in accept_ip_struct;
int accept_ip_address;
int client_ip_address;
Ui::tcpipClass ui;
public:
tcpip_server(int accept_ip_addr,
ushort port_port,
p_VOID_FUNCT p_void_funct, Ui::tcpipClass uip);
//:
// accept_ip_address(accept_ip_addr),
// port(port_port),
// ui(uip);
// destructor
~tcpip_server()
{
close(socketfd); /* close original socket */
}
static int socketfd, newsocketfd;
static QList<QString> qlist;
static bool running;
static QStringList qstrList;
static void localClose()
{
qDebug()<<"close detected";
running = false;
close(socketfd); // obviously this is NOT a definition
close(newsocketfd);
exit(0);
}
static void* str_echo(void* p_void);
// struct sock_addr_in client_ip_struct;


};
bool tcpip_server::running = true;
int tcpip_server::socketfd = 0;
int tcpip_server::newsocketfd = 0;
QStringList tcpip_server::qstrList = QStringList();
QList<QString> tcpip_server::qlist = QList<QString>();
#endif /*TCPIP_SERVER_H_*/


link errors for each static variable!



make release
make -f Makefile.Release
make[1]: Entering directory `/home/landon4/workspace/tcpip'
g++ -c -pipe -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -Irelease -I. -o release/tcpip_client.o tcpip_client.cpp
g++ -c -pipe -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -Irelease -I. -o release/tcpip_server.o tcpip_server.cpp
tcpip_client.h: In constructor ‘tcpip_client::tcpip_client(int, ushort, bool, Ui::tcpipClass)’:
tcpip_client.h:14: warning: ‘tcpip_client::accept_ip_address’ will be initialized after
tcpip_client.h:12: warning: ‘ushort tcpip_client::port’
tcpip_client.cpp:17: warning: when initialized here
tcpip_client.cpp: At global scope:
tcpip_client.cpp:17: warning: unused parameter ‘ui’
tcpip_client.cpp: In member function ‘int tcpip_client::tcp_write(char*, int)’:
tcpip_client.cpp:64: warning: ignoring return value of ‘ssize_t write(int, const void*, size_t)’, declared with attribute warn_unused_result
g++ -c -pipe -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -Irelease -I. -o release/main.o main.cpp
In file included from tcpip_server.h:11,
from tcpip_server.cpp:2:
sock_io.cpp: In member function ‘int sock_io::tcp_write(char*, int)’:
sock_io.cpp:18: warning: ignoring return value of ‘ssize_t write(int, const void*, size_t)’, declared with attribute warn_unused_result
tcpip_server.h: In constructor ‘tcpip_server::tcpip_server(int, ushort, void* (*)(void*), Ui::tcpipClass)’:
tcpip_server.h:21: warning: ‘tcpip_server::accept_ip_address’ will be initialized after
tcpip_server.h:19: warning: ‘ushort tcpip_server::port’
tcpip_server.cpp:4: warning: when initialized here
tcpip_server.cpp:43: warning: suggest parentheses around assignment used as truth value
g++ -c -pipe -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -Irelease -I. -o release/tcpip.o tcpip.cpp
/usr/lib/qt4/bin/moc -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -Irelease -I. tcpip.h -o release/moc_tcpip.cpp
In file included from tcpip_server.h:11,
from tcpip.cpp:8:
sock_io.cpp: In member function ‘int sock_io::tcp_write(char*, int)’:
sock_io.cpp:18: warning: ignoring return value of ‘ssize_t write(int, const void*, size_t)’, declared with attribute warn_unused_result
g++ -c -pipe -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -Irelease -I. -o release/moc_tcpip.o release/moc_tcpip.cpp
g++ -o tcpip release/tcpip_client.o release/tcpip_server.o release/main.o release/tcpip.o release/moc_tcpip.o -lQtGui -lQtCore -lpthread
make[1]: Leaving directory `/home/landon4/workspace/tcpip'
release/tcpip.o:/usr/include/QtCore/qlist.h:527: multiple definition of `tcpip_server::qstrList'
release/tcpip_server.o:/usr/include/QtCore/qatomic_i386.h:90: first defined here
release/tcpip.o:/usr/include/QtCore/qlist.h:559: multiple definition of `tcpip_server::qlist'
release/tcpip_server.o:/usr/lib/gcc/i386-redhat-linux/4.3.0/../../../../include/c++/4.3.0/iostream:77: first defined here
release/tcpip.o:/home/landon4/workspace/tcpip/tcpip.cpp:175: multiple definition of `tcpip_server::socketfd'
release/tcpip_server.o:/home/landon4/workspace/tcpip/tcpip_server.cpp:90: first defined here
release/tcpip.o:(.data+0x0): multiple definition of `tcpip_server::running'
release/tcpip_server.o:(.data+0x0): first defined here
release/tcpip.o:/home/landon4/workspace/tcpip/tcpip.cpp:175: multiple definition of `tcpip_server::newsocketfd'
release/tcpip_server.o:/usr/include/QtCore/qatomic_i386.h:90: first defined here
collect2: ld returned 1 exit status
make[1]: *** [tcpip] Error 1
make: *** [release] Error 2

jacek
17th August 2008, 02:40
bool tcpip_server::running = true;
int tcpip_server::socketfd = 0;
int tcpip_server::newsocketfd = 0;
QStringList tcpip_server::qstrList = QStringList();
QList<QString> tcpip_server::qlist = QList<QString>();
This should be in a .cpp file, not a header.

Why are they static anyway?

landonmkelsey
18th August 2008, 05:42
Made some changes and am now getting fewer but equally mystifying compile errors! The call to close(int) didn't cause a problem in

tcpip_server::str_echo(void* p_void)

but causes a problem in

void tcpip::localClose()!
The difference is that class tcpip has the Q_OBJECT but class tcpip_server does not have the Q_OBJECT!

The remaining question is simple: why?
The compiler seems to regard close as a tcpip function!



#include "tcpip.h"
#include <iostream>
#include <sstream>
#include <exception>

#include "tcpip_server.h"
#include "tcpip_client.h"
#include "tstash.h"
#include <QStringListModel>
using namespace std;
#include "thread.cpp"
#include "sock_io.cpp"
#include <QtDebug>

tcpip::tcpip(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
connect( ui.pushButtonStartTCPServer, SIGNAL(clicked()), this, SLOT(StartTCPServer()) );
connect( ui.pushButtonStartTCPClient, SIGNAL(clicked()), this, SLOT(StartTCPClient()) );
connect( ui.pushButtonClose, SIGNAL(clicked()), this, SLOT(localClose()) );

ui.listWidgetServer->addItem(QString("server constructor"));

}
tcpip::~tcpip()
{
delete ptcpipThreadStart;
}
void tcpip::StartTCPServer()
{
ui.listWidgetServer->addItem(QString("server1 StartTCPServer"));
QStringList qsl;
qsl.append(QString("abcd1234"));
QStringListModel *qStringListModel;
qStringListModel = new QStringListModel;
qStringListModel->setStringList(tcpip_server::qstrList);

ui.listViewServer->setModel(qStringListModel);

QApplication::processEvents();
bool ok = true;
QString qstr = ui.lineEditTCPIPServerPortServer->text();
port = qstr.toInt(&ok);
//qDebug()<<" server port "<<port;
ui.lineEditServerStatus->setText("server started");
QApplication::processEvents();
tcpipThread* ptcpipThreadStart = new tcpipThread(ui, port);
ptcpipThreadStart->start();
}

void tcpip::StartTCPClient()
{
ui.listWidgetClient->addItem(QString("client StartTCPClient"));
bool ok = true;
QString qstr = ui.lineEditTCPIPServerPortClient->text();

ushort port = qstr.toInt(&ok);
tcpip_client* p_client = new tcpip_client((int)19999,port,FALSE, ui);

str_client(p_client, ui); /* process the request */
close();
}
#define MAXLINE 512

void* tcpip_server::str_echo(void* p_void)
{
sock_io* p_sio = (sock_io*)p_void;
int n;
char line[MAXLINE];
const char* pline = line;
bool exitNow = false;

do
{
n = p_sio->tcp_read(line);
if(!n)
{
running = false;
close(socketfd);
close(newsocketfd);
qDebug()<<"str_echo tried to close";
exit(0);
}
line[n] = '\n';
line[n+1] = 0;
n++;
QString qstr(pline);
qstr = qstr.trimmed();
qstrList.append(QString(pline));
qDebug()<<"_____"<<qstr.size()<<"_________";
qDebug()<<"_____"<<QString("close").size()<<"_________";
if (qstr == QString("close"))
{
qDebug()<<"close detected";
running = false;
close(socketfd);
close(newsocketfd);
exitNow = true;
break;
}
p_sio->tcp_write(line, n);
} while(!exitNow);
void* p_void_exit=0;
delete p_sio;
if (exitNow) exit(0);
pthread_exit(p_void_exit);
return p_void_exit;
}

#define MAXLINE 512

void tcpip::str_client(tcpip_client* tcpip_x, Ui::tcpipClass ui)
{
int n;
char sendline[MAXLINE], recvline[MAXLINE + 1];
bool done=FALSE;
while (!done)
{
cout<<"enter keyboard string"<<endl;
cin.getline(sendline,256);
n = strlen(sendline);
if(n==0) break;
sendline[n] = '\n'; /* newline terminate */
sendline[n+1] = 0;/* newline terminate */
n++;
ui.listWidgetClient->addItem(QString("client constructorstr_client"));
tcpip_x->tcp_write(sendline,n);
cout<<"sendline:"<<sendline<<endl;
n = tcpip_x->tcp_read(recvline);
recvline[n] = '\n'; /* null terminate */
recvline[n+1] = 0; /* null terminate */
n++;
cout<<"bytes received "<<n;
cout<<"client received:echo = "<<recvline<<endl;
}
}
void tcpip::currChanged(QWidget*){};

void tcpipThread::run()
{
tcpip_server* p_serv = new tcpip_server((int)19999,port,tcpip_server::str_ech o, ui);
qDebug()<<"should not happen before client calls in...back from CTOR";
delete p_serv;
}

void tcpip::localClose()
{
qDebug()<<"close detected";
tcpip_server::running = false;
close(tcpip_server::socketfd);
close(tcpip_server::newsocketfd);
exit(0);
}
compile errors:
make debug
make -f Makefile.Debug
make[1]: Entering directory `/home/landon4/workspace/tcpip'
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -Idebug -I. -o debug/tcpip.o tcpip.cpp
make[1]: Leaving directory `/home/landon4/workspace/tcpip'
tcpip.cpp: In member function ‘void tcpip::localClose()’:
tcpip.cpp:187: error: no matching function for call to ‘tcpip::close(int&)’
/usr/include/QtGui/qwidget.h:477: note: candidates are: bool QWidget::close()
tcpip.cpp:188: error: no matching function for call to ‘tcpip::close(int&)’
/usr/include/QtGui/qwidget.h:477: note: candidates are: bool QWidget::close()
make[1]: *** [debug/tcpip.o] Error 1
make: *** [debug] Error 2



#include "tcpip_server.h"
tcpip_server::tcpip_server(int accept_ip_addr, ushort port_port,
p_VOID_FUNCT p_void_funct, Ui::tcpipClass uip):
accept_ip_address(accept_ip_addr),
port(port_port),
ui(uip)
{
int setreuse=1;
int istatus;

if ( (socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
qDebug()<<"socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0";
return;
}
qDebug()<<"socketfd = socket(AF_INET, SOCK_STREAM, 0))"<<socketfd;
int errorDup = dup2(socketfd,20);
qDebug()<<"errorDup"<<errorDup;
qDebug()<<"socketfd = socket(AF_INET, SOCK_STREAM, 0))"<<socketfd;

memset((char *) &serv_addr,0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(SERV_TCP_PORT);

if(istatus = setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, (char *) &setreuse, sizeof(setreuse)))
{
qDebug()<<"setsockopt";
return;
}

if (bind(socketfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
qDebug()<<"bind";
return;
}

listen(socketfd, 5);
tstash<sock_io> vector_psio;
void* p_void = NULL;
running = true;
while(1)
{
QApplication::processEvents();
clilen = sizeof(cli_addr);
qDebug()<<"enter accept()";
newsocketfd = accept(socketfd, (struct sockaddr *) &cli_addr, &clilen);
qDebug()<<"newsocketfd"<<newsocketfd;
qDebug()<<"exit accept()";
if (newsocketfd < 0)
{
return;
}
sock_io* p_sio = new sock_io( newsocketfd);
p_void = (void*)p_sio;
tthread* p_thread = new tthread( p_void_funct, p_void);
p_thread->run();
}
}

Just to break things loose, I made the following change:

void tcpip::localClose()
{
qDebug()<<"close detected";
tcpip_server::running = false;
::close(tcpip_server::socketfd); // changed
::close(tcpip_server::newsocketfd); // changed
exit(0);
}

Now I get new link errors from that "qatomic thing"


make debug
make -f Makefile.Debug
make[1]: Entering directory `/home/landon4/workspace/tcpip'
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -Idebug -I. -o debug/tcpip.o tcpip.cpp
/usr/lib/qt4/bin/moc -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -Idebug -I. tcpip.h -o debug/moc_tcpip.cpp
g++ -c -pipe -g -Wall -W -D_REENTRANT -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/lib/qt4/mkspecs/linux-g++ -I. -I/usr/include/QtCore -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtGui -I/usr/include -Idebug -I. -o debug/moc_tcpip.o debug/moc_tcpip.cpp
g++ -o tcpip debug/tcpip_client.o debug/tcpip_server.o debug/main.o debug/tcpip.o debug/moc_tcpip.o -lQtGui -lQtCore -lpthread
make[1]: Leaving directory `/home/landon4/workspace/tcpip'
debug/tcpip.o: In function `__static_initialization_and_destruction_0':
/usr/include/QtCore/qlist.h:364: multiple definition of `tcpip_server::qstrList'
debug/tcpip_server.o:/home/landon4/workspace/tcpip/tcpip_server.cpp:90: first defined here
debug/tcpip.o: In function `__static_initialization_and_destruction_0':
/home/landon4/workspace/tcpip/tcpip.cpp:190: multiple definition of `tcpip_server::qlist'
debug/tcpip_server.o:/home/landon4/workspace/tcpip/tcpip_server.cpp:90: first defined here
debug/tcpip.o:/usr/include/QtCore/qatomic_i386.h:82: multiple definition of `tcpip_server::socketfd'
debug/tcpip_server.o:/home/landon4/workspace/tcpip/tcpip_server.cpp:90: first defined here
debug/tcpip.o:(.data+0x0): multiple definition of `tcpip_server::running'
debug/tcpip_server.o:(.data+0x0): first defined here
debug/tcpip.o:/usr/include/QtCore/qatomic_i386.h:120: multiple definition of `tcpip_server::newsocketfd'
debug/tcpip_server.o:/home/landon4/workspace/tcpip/tcpip_server.cpp:90: first defined here
collect2: ld returned 1 exit status
make[1]: *** [tcpip] Error 1
make: *** [debug] Error 2


BINGO! I moved the static definitions as you suggested and got rid of the qatomic errors!

No errors! Thanks! In many years of C++ programming I never noticed a need for defining static variables just ahead of the implementation code!

Maybe it is the Q_OBJECT thing!

Unfortunately, the following changes are necessary!

void tcpip::localClose()
{
qDebug()<<"close detected";
tcpip_server::running = false;
::close(tcpip_server::socketfd);
::close(tcpip_server::newsocketfd);
exit(0);
}

program is now working perfectly (for the desired current state)

thanks!