QList + QVariant + dbus, what difference? - c++

Code bellow. In this variants it doesn't work, it says:
int main(int, char**): mount error msg `Method "FilesystemMount" with signature "bas" on interface "org.freedesktop.UDisks.Device" doesn't exit.
But if I replace "#if 0" with "#if 1" all will works fine.
Can you explain?
#include <cstdio>
#include <cstdlib>
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
#include <QtDBus/QDBusMessage>
#include <QtDBus/QDBusPendingReply>
#include <QtDBus/QDBusConnection>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
if (argc != 2) {
fprintf(stderr, "Usage: %s path/to/device\n", argv[0]);
return EXIT_FAILURE;
}
const QString dev_path(argv[1]);
auto mount_call = QDBusMessage::createMethodCall("org.freedesktop.UDisks", dev_path, "org.freedesktop.UDisks.Device", "FilesystemMount");
#if 0
QList<QVariant> args;//WHY THIS WORKS???
args << QVariant(QString()) << QVariant(QStringList("sync"));
#else
QList<QVariant> args;//AND WHY THIS NOT WORKS???
QVariant filesystem_type(QString());
QVariant opts(QStringList("sync"));
args << filesystem_type << opts;
#endif
mount_call.setArguments(args);
QDBusPendingReply<QVariantMap> mount_res = QDBusConnection::systemBus().call(mount_call);
if (!mount_res.isValid())
fprintf(stderr, "%s: mount error msg `%s'\n", __PRETTY_FUNCTION__, mount_res.error().message().toLocal8Bit().data());
return app.exec();
}
So for me this looks likes:
Container<T> c;
T a;
T b;
c.append(a);
c.append(b);
vs
Container c;
c.append(T());
c.append(T());
but the content of "c" should be the same after end of both control flow?

Ok, I found the reason:
compiler thought that:
QVariant filesystem_type(QString());
is a pointer to function, not a QVariant object;

Related

ASSERT: "allArguments.size() == origArgc"

I'm having this error in my Qt Application:
Debug Error!
Program: C:\Qt\Qt5.1.1\5.1.1\msvc2012_64\bin\QtCored.dll
Module: 5.1.1 File: global\qglobal.cpp
Line: 2014
ASSERT: "allArguments.size() == origArgc" in file
kernel\qcoreapplication.cpp, line 2095
#include <QCoreApplication>
#include <QDebug>
#include <QStringList>
int main(int argc, char *argv[])
{
QCoreApplication app(argc,argv);
qDebug()<<"argc:" << argc;
qDebug()<<"arguments:"<<app.arguments().length();
return 0;
}
Why is that so?
The issue was that I was passing arguments with a new line character in it.
After I removed, it worked again.

sqlite3_exec()! = SQLITE3_OK. Trying to tranfer in OOP won't work

I'm trying to work with a database in C++. I made a program that opens the database and then creates the tables in procedural programming.
When trying to make it in OOP, sqlite3_exec() != SQLITE_OK
I am new at this, so be gentle.
Here is main.cpp:
#include <iostream>
#include "sqlite3.h"
#include "Table.h"
using namespace std;
int openDatabase(sqlite3 *db);
int main() {
sqlite3 *db;
string columnValues, rowValues; // these are for query
Table Personal;
Personal.SettableName("PERSONAL");
columnValues = "NUME TEXT, ID TEXT"; // this is just an example
openDatabase(db);
Personal.createTable(db, columnValues);
sqlite3_close(db);
return 0;
}
Table.cpp
#include <string>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "Table.h"
#include "sqlite3.h"
using namespace std;
static int callback(void *data, int argc, char **argv, char **azColName) {
int i;
fprintf(stderr, "%s: ", (const char*)data);
for(i = 0; i < argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
void executeSqlStatement(sqlite3 *db,const char* sql) {
int rc = 0 ;
char *zErrMsg = 0;
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg); // Here it doesn't work, rc=21;
if( rc != SQLITE_OK ) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
else {
fprintf(stdout, "Operation done successfully\n");
}
}
void Table::createTable(sqlite3 *db, string columnDetails) {
this->sqlCommand = "CREATE TABLE ";
this->sqlCommand += (this->tableName + " (" + columnDetails + ");");
executeSqlStatement(db, this->sqlCommand.c_str());
printf(sqlCommand.c_str());
}
And Table.h
#include "sqlite3.h"
using namespace std;
void executeSqlStatement(sqlite3 *db);
static int callback(void *data, int argc, char **argv, char **azColName);
class Table
{
public:
void SettableName(string val){tableName = val;}
void createTable(sqlite3 *db, string columnDetails);
string tableName;
string sqlCommand;
};
Including the sqlite3.h file in all three files is not necessary, as Table.h was included by both the cpp files, so you only needed to have it in that file.
The sqlite3.h file is also a system file, so using include <sqlite3.h> instead of include "sqlite3.h" makes it clearer where the file is coming from.
I would recommend compiling with the -Wall and -Wextra flags - at first they appear to make loads of complaints but it is worth paying attention to the problems reported and working out how to fix them.
Table.h
#include <sqlite3.h>
using namespace std;
void executeSqlStatement(sqlite3 *db);
int callback(void *data, int argc, char **argv, char **azColName);
class Table
{
public:
void SettableName(string val){tableName = val;}
void createTable(sqlite3 *db, string columnDetails);
string tableName;
string sqlCommand;
};
Table.cpp
#include <string>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "Table.h"
using namespace std;
int callback(void *data, int argc, char **argv, char **azColName) {
int i;
fprintf(stderr, "%s: ", (const char*)data);
for(i = 0; i < argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
void executeSqlStatement(sqlite3 *db,const char* sql) {
int rc = 0 ;
char *zErrMsg = 0;
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg); // Here it doesn't work, rc=21;
if( rc != SQLITE_OK ) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
}
else {
fprintf(stdout, "Operation done successfully\n");
}
}
void Table::createTable(sqlite3 *db, string columnDetails) {
this->sqlCommand = "CREATE TABLE ";
this->sqlCommand += (this->tableName + " (" + columnDetails + ");");
executeSqlStatement(db, this->sqlCommand.c_str());
printf(sqlCommand.c_str());
}
main.cpp
#include <iostream>
#include "Table.h"
using namespace std;
int main() {
sqlite3 *db;
sqlite3_open_v2("test.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
string columnValues, rowValues; // these are for query
Table Personal;
Personal.SettableName("PERSONAL");
columnValues = "NUME TEXT, ID TEXT"; // this is just an example
Personal.createTable(db, columnValues);
sqlite3_close(db);
return 0;
}
On my github I have a working version of your code, with a (borrowed) makefile to pull the files together so I just have to type make debug to compile the code.
make debug && bin/debug/hello
will build the file, and if the compilation was successful run the executable.

Installing message handler

I have tried to create a log file for an application by installing a message handler using qinstallMessageHandler() function. My program is as follows:
#include <QCoreApplication>
#include <QtDebug>
#include <QDir>
#include <fstream>
#include <iostream>
#include <QtCore>
#include <stdio.h>
#include <stdlib.h>
FILE *fd;
void myMessageOutput(QtMsgType type, const char *msg)
{
QString timeStamp = QTime::currentTime().toString("hh:mm:ss:zzz");
switch (type) {
case QtDebugMsg:
fprintf(fd, "[%s]", timeStamp.toStdString().c_str());
fprintf(fd, "[Debug] %s\n", msg);
break;
case QtWarningMsg:
fprintf(fd, "[%s]", timeStamp.toStdString().c_str());
fprintf(fd, "[Warning] %s\n", msg);
break;
case QtCriticalMsg:
fprintf(fd, "[%s]", timeStamp.toStdString().c_str());
fprintf(fd, "[Critical] %s\n", msg);
break;
case QtFatalMsg:
fprintf(fd, "[%s]", timeStamp.toStdString().c_str());
fprintf(fd, "[Fatal] %s\n", msg);
abort();
}
}
int main(int argc, char *argv[])
{
fd = fopen("log.txt", "a");
qInstallMessageHandler(myMessageOutput);
QCoreApplication a(argc, argv);
qDebug()<<"\t Hello World!!! \n";
return a.exec();
}
But after compiling I get the following error:
error: invalid conversion from 'void ()(QtMsgType, const char)' to 'QtMessageHandler {aka void (*)(QtMsgType, const QMessageLogContext&, const QString&)}' [-fpermissive]
Anyone here who have faced the same problem earlier?
It looks like you switch to Qt5 and used the message handler function signature defined in Qt4.x. You need to declare your message handler as follows:
void myMessageOutput(QtMsgType type,
const QMessageLogContext &context,
const QString &msg)
{
[..]
}
instead.

C++ memory leak while using std::string in child process

I'm having problem with this piece of code, valgrind detects memory leaks in std::basic_string and I don't know what am I doing wrong. The leak is only when std::string is used in child process. Could you please tell me, where the problem is? I've never used fork() in C++ before so I don't have much exprience.
#include <iostream>
#include <string>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
pid_t childPid = fork();
if (childPid == -1)
{
perror("fork");
return EXIT_FAILURE;
}
else if (childPid == 0)
{
std::cout << "Child PID: " << getpid() << std::endl;
std::string str("something"); //valgrind detects mem leak here
_Exit(EXIT_SUCCESS);
}
else
{
//std::string str("something"); //but not here
}
waitpid(-1, 0, 0);
return EXIT_SUCCESS;
}
_Exit will not run any destructors or atexit functions, it simply ends immediately.
Obviously this punches a giant hole through RAII, so Don't Do That.
One way of implementing Don't Do That while maintaining the same exit strategy might be:
template <typename Func, typename... Args>
int wrap_cpp_code(Func&& func, Args&&.. args)
{
try
{
return std::forward<Func>(func)(std::forward<Args>(args)...);
}
catch (...)
{
return EXIT_FAILURE;
}
}
Which won't cough up an return value until all destructors under its scope are run, giving:
int child_main(int argc, char *argv[])
{
std::cout << "Child PID: " << getpid() << std::endl;
std::string str("something");
return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
pid_t childPid = fork();
if (childPid == -1)
{
perror("fork");
return EXIT_FAILURE;
}
else if (childPid == 0)
{
int ret = wrap_cpp_code(child_main, argc, argv);
_Exit(ret);
}
else
{
/*
int ret = wrap_cpp_code(xyz, argc, argv);
*/
}
waitpid(-1, 0, 0);
return EXIT_SUCCESS;
}
But this still fails to account for atexit functions or global destructors. So still Avoid Doing That.

printf causes crash

#include <stdio.h>
int main(char sendbuf[100])
{
printf (sendbuf);
return 0;
}
Somehow this very basic program crashes when I try to use it, it's meant to print up whatever is typed as a parameter. If I remove the line "printf (sendbuf);" the crash goes away.
The first argument to main is the number of parameters. The second argument is an array of strings. The first element (index 0) of the second argument is the name of your program:
#include <stdio.h>
int main(int c, char **argv)
{
printf ("%s\n", c > 1 ? argv[1] : "No Argument");
return 0;
}
Your first parameter must be an integer, not a char array. Here is the right program:
#include <stdio.h>
int main(int argc, char* argv[])
{
if (argc > 1) {
printf( argv[1] );
}
else {
printf( "No arguments provided" );
}
return 0;
}
argv[0] is your program name, so argv[1] is the first parameter provided on teh command line.
C supports two forms of main function:
int main() { /* ... */ }
and
int main(int argc, char* argv[]) { /* ... */ }
To take parameter from main, you need to change your code to:
#include <stdio.h>
int main(int argc, char* argv[])
{
if (argc > 1){
printf ("%s\n", argv[0]);
}
return 0;
}
Or use stream:
#include <iostream>
int main(int argc, char* argv[])
{
if (argc > 1){
std::cout << argv[0]) << std::endl;
}
return 0;
}
argv[0] is application name, input parameters starts from argv[1] if any.
An implementation must support the following two definitions of main:
int main() { }
int main(int argc, char* argv[]) { }
It is implementation-defined whether they support any other definitions. I don't know of any implementation that allows int main(char*) though (which is what yours is equivalent to).
This will print everything you type on the command line after the program name, even with spaces. It will not crash if you type nothing after the program name.
#include <stdio.h>
int main(int argc, char **argv)
{
for(int i=1; i<=argc; ++i) {
printf("%s\n", argv[i]);
}
}