Qt Application crash when setting QTimer interval - android

This is my first question, the reason i signed up to the site. I'm developing a game using Qt 5.9 and I use QTimer to spawn enemies on the screen. Everytime the timer's timeout function is called, an enemy is spawned.
What i try to do is if a player kills let's say 10 enemies, the timer interval decreases, so the enemies will spawn more frequently, making the game a little bit more challenging. The first time the timer interval is set, the game runs perfectly, but the second time the setInterval() method is called, when the player kills 10 enemies, the game suddenly crashes. I tried debugging it to figure out what might cause it, and it seems that it crashes when i try to set the spawnInterval.
I'm fairly new to coding so any advice is appreciated! Here are the relevant source files and codes from my code:
main.cpp
#include <QApplication>
#include <game.h>
Game * game;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
game = new Game();
game->show();
return a.exec();
}
game.h:
#include <QGraphicsScene>
#include <QWidget>
#include <QGraphicsView>
#include "Player.h"
#include "score.h"
#include "Health.h"
class Game: public QGraphicsView{
public:
Game(QWidget * parent=0);
QGraphicsScene * scene;
Player * player;
Score * score;
Health * health;
void setSpawnInterval(int spawnValue);
int getSpawnInterval();
void setTimerInterval();
private:
int spawnInterval = 1000;
};
#endif // GAME_H
game.cpp:
QTimer * timer1 = new QTimer();
QObject::connect(timer1,SIGNAL(timeout()),player,SLOT(spawn()));
timer1->start(getSpawnInterval());
}
void Game::setSpawnInterval(int spawnValue){
//this is the part where it crashes
spawnInterval = spawnValue;
}
int Game::getSpawnInterval(){
return spawnInterval;
}
score.h
#ifndef SCORE_H
#define SCORE_H
#include <QGraphicsTextItem>
class Score: public QGraphicsTextItem{
public:
Score(QGraphicsItem * parent=0);
void increase();
int getScore();
private:
int score;
};
#endif // SCORE_H
score.cpp
#include "score.h"
#include <QFont>
#include "game.h"
#include <QTimer>
void Score::increase()
{
score++;
if(score > 3){
Game * game;
game->setSpawnInterval(200);}
//Draw the text to the display
setPlainText(QString("Score: ") + QString::number(score));
}
int Score::getScore()
{
return score;
}
player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <QGraphicsRectItem>
#include <QEvent>
#include <QObject>
class Player: public QObject, public QGraphicsRectItem{
Q_OBJECT
public:
Player(QGraphicsItem * parent=0);
void keyPressEvent(QKeyEvent * event);
int jumpPhaseNumber = 0;
bool jumpRun = false;
public slots:
void spawn();
void jumpPhase();
};
#endif
player.cpp
void Player::spawn()
{
Enemy * enemy = new Enemy();
scene()->addItem(enemy);
}

Seems you are creating two instance of class game.
I suggest you to use static variables for accessing from multi classes.
add this class to your project:
.cpp
#include "settings.h"
int Settings::spawnInterval = 1000;
Settings::Settings(QObject *parent) : QObject(parent)
{
}
.h
#ifndef SETTINGS_H
#define SETTINGS_H
#include <QObject>
#include <QString>
class Settings : public QObject
{
Q_OBJECT
public:
explicit Settings(QObject *parent = 0);
static int spawnInterval;
};
#endif // SETTINGS_H
now we have a static variable name spawnInterval, you can access it (set/get) from any classes that include settings class like this:
#include <settings.h>
Settings::spawnInterval = 100; // set
int value = Settings::spawnInterval; //get

This line: Game * game; game->setSpawnInterval(200) causes your program to crash: you must initialize the game pointer; to fix this, for example, you can hold a reference (pointer) of game inside the Score class, thus letting you call setSpawnInterval; I would construct Score inside Game's constructor passing thisas a parameter; this saves you from creating a new class, as #aghilpro suggested. Actually a struct would be better since your information is public and accessible from other classes without the need to implement getters/setters.

Related

CVE-2017-10661 triggering

I'm trying to make a c program which triggers CVE-2017-10661.
As far as I understand because might_cancel mechanism it isn't properly protected if you make parallel operations on the file descriptor you can cause a crash.
I believe these parallel operations are read, poll etc right?
Currently i have written this piece of code.
#include <sys/timerfd.h>
#include <sys/poll.h>
#include <sys/epoll.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
int main(int ac, char *av[])
{
int timerfd;
int epollfd;
struct itimerspec timerValue;
uint64_t exp;
ssize_t s;
/* set timerfd */
timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
if (timerfd < 0) {
printf("failed to create timer fd\n");
exit(1);
}
bzero(&timerValue, sizeof(timerValue));
timerValue.it_value.tv_sec = 1;
timerValue.it_value.tv_nsec = 0;
timerValue.it_interval.tv_sec = 1;
timerValue.it_interval.tv_nsec = 0;
/* start timer */
if (timerfd_settime(timerfd, 0, &timerValue, NULL) < 0) {
printf("could not start timer\n");
exit(1);
}
s = read( timerfd, &exp, sizeof(uint64_t));
exit(0);
}
As you can see i set up a timer and then i only do a reading operation. Is there any way t trigger the bug by doing mupltiple read or pollings?
The race condition is triggered by timerfd_settime() -> timerfd_setup_cancel() -> timerfd_setup_cancel(). So you should use multiple threads to do timerfd_settime with the flag as TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET.
Here is the POC I found online.

vlc/libvlc - how to get a reference to a custom vlc module

I am creating android application that uses libvlc to play a video.
Since vlc/libvlc doesnt have any kind of event/callback for subtitles i have created my own text renderer module in modules/text_rendere/spucallback
Module compiles, but i have two problems.:
I dont see any log messages from this module
How can i use this module from libvlc
callback.h
typedef void (*spu_cb_t)(text_segment_t *p_segment);
struct spu_cb_t {
spu_cb_t cb;
};
struct spu_cb_t *callback;
callback.c
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
/* VLC core API headers */
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_interface.h>
#include <vlc_filter.h>
#include "callback.h"
static int Open(vlc_object_t *);
static void Close(vlc_object_t *);
static int RenderText(filter_t *,
subpicture_region_t *p_region_out,
subpicture_region_t *p_region_in,
const vlc_fourcc_t *p_chroma_list);
/* Module descriptor */
vlc_module_begin()
set_shortname(N_("SPU Callback "))
set_description(N_("SPU Callback module"))
set_capability("text renderer", 0)
set_callbacks(Open, Close)
set_category(CAT_VIDEO)
vlc_module_end ()
static int Open(vlc_object_t *p_this)
{
filter_t *p_filter = (filter_t *)p_this;
p_filter->pf_render = RenderText;
printf("spucallback:Open");
callback = (spu_cb_t*) malloc(sizeof(spu_cb_t));
if (!callback)
goto error;
return VLC_SUCCESS;
error:
free(callback);
return VLC_EGENERIC;
}
static void Close(vlc_object_t *p_this)
{
printf("spucallback:Close");
free(callback->cb);
free(callback);
}
static int RenderText(filter_t *p_filter,
subpicture_region_t *p_region_out,
subpicture_region_t *p_region_in,
const vlc_fourcc_t *p_chroma_list)
{
text_segment_t *p_segment = p_region_in->p_text;
callback->cb(p_segment);
printf("spucallback:RenderText");
return VLC_SUCCESS;
}
Code is not yet finished obviously
This log messages might be related:
[e41bfa2c] core spu text: looking for text renderer module matching "spucallback": 1 candidates
[e41bfa2c] core spu text: no suitable access module for `file:///vendor/etc/fallback_fonts.xml'
[e41bfa2c] core spu text: using text renderer module "freetype"

Use of Classes in Cocos2d-x to create an "Enemy" to extend Layer

Pretty new to Cocos2dx and C++ from an Objective-C background. I'm making a game where you can have between 1-10 enemies on the screen at a time. Each enemy has 1 sprite for its body and 2 stats (health & damage).
In the past with Objective-C I've been able to define a Class.h/Class.mm file and fill it with as many variables as I want (health, speed, height, weight, color, etc), but I'm having trouble figuring out how to do this in Cocos2dx.
Here is a simplified project that isolates the problem I'm having. I'm sure it's something straight forward but I'm having trouble looking up the solution
//-----Enemy.h
#include "cocos2d.h"
USING_NS_CC;
class Enemy : public cocos2d::Layer{
public:
virtual bool init();
CREATE_FUNC(Enemy);
void setHealth(int val);
private:
int myHealth;
Sprite *body;
Sprite *weapon;
};
//-----Enemy.cpp
#include "Enemy.h"
USING_NS_CC;
bool Enemy::init()
{
if ( !Layer::init() )
return false;
return true;
}
void setHealth(int newHealth)
{
//myHealth = newHealth;
}
//-----HelloWorldScene.h
#include "cocos2d.h"
USING_NS_CC;
class HelloWorld : public cocos2d::Layer
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(HelloWorld);
};
//-----HelloWorldScene.cpp
#include "HelloWorldScene.h"
#include <iomanip>
#include "Enemy.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
if ( !Layer::init() )
return false;
Enemy *newEnemy = Enemy::create();
//newEnemy->setHealth(100);
this->addChild(newEnemy);
return true;
}
This compiles fine except for the 2 commented lines, which cause errors.
Please help, thanks in advance!
Without knowing your error message exactly, it looks like you are missing the class name in your setHealth method in Enemy.cpp
Change your method declaration in your Enemy.h
From:
void setHealth(int val);
To:
void setHealth(int newHealth);
Then in your Enemy.cpp file change the following.
From:
void setHealth(int newHealth)
To:
void Enemy::setHealth(int newHealth)

QSetting doesn't works fine for me

I've wrote a simple application to use QSettings. Can someone tell me what wrong I'm doing here..
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QWidget *pMainWidget;
QHBoxLayout *pMainLayout;
QSettings *pSetting;
QLabel *pLabel;
QPushButton *pButtonShow;
QPushButton *pButtonSet;
QLineEdit *pLineEdit;
QString pSettingFile;
public slots:
void showSettingData();
void setData();
};
mainwindow.cpp
#include "mainwindow.h"
#include <QtCore/QCoreApplication>
#include <QApplication>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
pMainWidget = new QWidget (parent);
pMainLayout = new QHBoxLayout(pMainWidget);
pLabel = new QLabel("Output comes here",pMainWidget);
pLineEdit = new QLineEdit();
pButtonShow = new QPushButton("Show", pMainWidget);
pButtonSet = new QPushButton("Set", pMainWidget);
setCentralWidget(pMainWidget);
pMainWidget->setLayout(pMainLayout);
pMainLayout->addWidget(pLabel);
pMainLayout->addWidget(pButtonShow);
pMainLayout->addWidget(pLineEdit);
pMainLayout->addWidget(pButtonSet);
pSettingFile = QApplication::applicationDirPath()+"settings.ini";
QObject::connect(pButtonShow, SIGNAL(clicked()), this, SLOT(showSettingData()));
QObject::connect(pButtonSet, SIGNAL(clicked()), this, SLOT(setData()));
}
MainWindow::~MainWindow()
{
}
void MainWindow::setData()
{
QSettings Setting(pSettingFile, QSettings::NativeFormat);
QString data = pLineEdit->text();
Setting.setValue("baseurl", data);
}
void MainWindow::showSettingData()
{
QSettings Setting(pSettingFile, QSettings::NativeFormat);
if (Setting.contains("baseurl"))
{
QString data = Setting.value("baseurl").toString();
pLabel->setText(data);
}
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
When I debug, it doesn't returns false for "Setting.contains("baseurl")"... Do we have to create the setting file?
The issue is that you are not calling sync after setting the data. Try to insert this line after the setting:
Setting.setValue("baseurl", data);
Setting.sync();
This should not be needed on Windows, but it seems to be necessary on Windows.
Also, as suggested in comments, I would suggest to use QSettings::IniFormat instead of QSettings::NativeFormat if you really want to use files rather than potentially registry on Windows.
You should also consider making the settings object as a class member rather than constructing it all the time.
Also, note that you may be using the wrong path unintentionally because you would have to add the "slash" character explicitly before the "settings.ini" file name. This is just a side note, however.

Segmentation fault when using dlclose(...) on android platform

I have some problems when using the dynamic loading API (<dlfcn.h>: dlopen(), dlclose(), etc) on Android.
I'm using NDK standalone toolchain (version 8) to compile the applications and libraries.
The Android version is 2.2.1 Froyo.
Here is the source code of the simple shared library.
#include <stdio.h>
int iii = 0;
int *ptr = NULL;
__attribute__((constructor))
static void init()
{
iii = 653;
}
__attribute__((destructor))
static void cleanup()
{
}
int aaa(int i)
{
printf("aaa %d\n", iii);
}
Here is the program source code which uses the mentioned library.
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
void *handle;
typedef int (*func)(int);
func bbb;
printf("start...\n");
handle = dlopen("/data/testt/test.so", RTLD_LAZY);
if (!handle)
{
return 0;
}
bbb = (func)dlsym(handle, "aaa");
if (bbb == NULL)
{
return 0;
}
bbb(1);
dlclose(handle);
printf("exit...\n");
return 0;
}
With these sources everything is working fine, but when I try to use some STL functions or classes, the program crashes with a segmentation fault, when the main() function exits, for example when using this source code for the shared library.
#include <iostream>
using namespace std;
int iii = 0;
int *ptr = NULL;
__attribute__((constructor))
static void init()
{
iii = 653;
}
__attribute__((destructor))
static void cleanup()
{
}
int aaa(int i)
{
cout << iii << endl;
}
With this code, the program crashes with segmentation fault after or the during main() function exit.
I have tried couple of tests and found the following results.
Without using of STL everything is working fine.
When use STL and do not call dlclose() at the end, everything is working fine.
I tried to compile with various compilation flags like -fno-use-cxa-atexit or -fuse-cxa-atexit, the result is the same.
What is wrong in my code that uses the STL?
Looks like I found the reason of the bug. I have tried another example with the following source files:
Here is the source code of the simple class:
myclass.h
class MyClass
{
public:
MyClass();
~MyClass();
void Set();
void Show();
private:
int *pArray;
};
myclass.cpp
#include <stdio.h>
#include <stdlib.h>
#include "myclass.h"
MyClass::MyClass()
{
pArray = (int *)malloc(sizeof(int) * 5);
}
MyClass::~MyClass()
{
free(pArray);
pArray = NULL;
}
void MyClass::Set()
{
if (pArray != NULL)
{
pArray[0] = 0;
pArray[1] = 1;
pArray[2] = 2;
pArray[3] = 3;
pArray[4] = 4;
}
}
void MyClass::Show()
{
if (pArray != NULL)
{
for (int i = 0; i < 5; i++)
{
printf("pArray[%d] = %d\n", i, pArray[i]);
}
}
}
As you can see from the code I did not used any STL related stuff.
Here is the source files of the functions library exports.
func.h
#ifdef __cplusplus
extern "C" {
#endif
int SetBabe(int);
int ShowBabe(int);
#ifdef __cplusplus
}
#endif
func.cpp
#include <stdio.h>
#include "myclass.h"
#include "func.h"
MyClass cls;
__attribute__((constructor))
static void init()
{
}
__attribute__((destructor))
static void cleanup()
{
}
int SetBabe(int i)
{
cls.Set();
return i;
}
int ShowBabe(int i)
{
cls.Show();
return i;
}
And finally this is the source code of the programm that uses the library.
main.cpp
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
#include "../simple_lib/func.h"
int main()
{
void *handle;
typedef int (*func)(int);
func bbb;
printf("start...\n");
handle = dlopen("/data/testt/test.so", RTLD_LAZY);
if (!handle)
{
printf("%s\n", dlerror());
return 0;
}
bbb = (func)dlsym(handle, "SetBabe");
if (bbb == NULL)
{
printf("%s\n", dlerror());
return 0;
}
bbb(1);
bbb = (func)dlsym(handle, "ShowBabe");
if (bbb == NULL)
{
printf("%s\n", dlerror());
return 0;
}
bbb(1);
dlclose(handle);
printf("exit...\n");
return 0;
}
Again as you can see the program using the library also does not using any STL related stuff, but after run of the program I got the same segmentation fault during main(...) function exit. So the issue is not connected to STL itself, and it is hidden in some other place. Then after some long research I found the bug.
Normally the destructors of static C++ variables are called immediately before main(...) function exit, if they are defined in main program, or if they are defined in some library and you are using it, then the destructors should be called immediately before dlclose(...).
On Android OS all destructors(defined in main program or in some library you are using) of static C++ variables are called during main(...) function exit. So what happens in our case? We have cls static C++ variable defined in library we are using. Then immediately before main(...) function exit we call dlclose(...) function, as a result library closed and cls becomes non valid. But the pointer of cls is stored somewhere and it's destructor should be called during main(...) function exit, and because at the time of call it is already invalid, we get segmentation fault. So the solution is to not call dlclose(...) and everything should be fine. Unfortunately with this solution we cannot use attribute((destructor)) for deinitializing of something we want to deinitialize, because it is called as a result of dlclose(...) call.
I have a general aversion to calling dlclose(). The problem is that you must ensure that nothing will try to execute code in the shared library after it has been unmapped, or you will get a segmentation fault.
The most common way to fail is to create an object whose destructor is defined in or calls code defined in the shared library. If the object still exists after dlclose(), your app will crash when the object is deleted.
If you look at logcat you should see a debuggerd stack trace. If you can decode that with the arm-eabi-addr2line tool you should be able to determine if it's in a destructor, and if so, for what class. Alternatively, take the crash address, strip off the high 12 bits, and use that as an offset into the library that was dlclose()d and try to figure out what code lives at that address.
I encountered the same headache on Linux. A work-around that fixes my segfault is to put these lines in the same file as main(), so that dlclose() is called after main returns:
static void* handle = 0;
void myDLClose(void) __attribute__ ((destructor));
void myDLClose(void)
{
dlclose(handle);
}
int main()
{
handle = dlopen(...);
/* ... real work ... */
return 0;
}
The root cause of dlclose-induced segfault may be that a particular implementation of dlclose() does not clean up the global variables inside the shared object.
You need to compile with -fpic as a compiler flag for the application that is using dlopen() and dlclose(). You should also try error handling via dlerror() and perhaps checking if the assignment of your function pointer is valid, even if it's not NULL the function pointer could be pointing to something invalid from the initialization, dlsym() is not guaranteed to return NULL on android if it cannot find a symbol. Refer to the android documentation opposed to the posix compliant stuff, not everything is posix compliant on android.
You should use extern "C" to declare you function aaa()

Categories

Resources