Problem with GtkTextBuffer , Confusing Runtime Error. Need Help? - c++

I am using this code:
class editbook
{
GtkWidget* _nbook;
std::vector<GtkWidget*> _srcset; //and so on...
...........................................................................................
void editbook::add_page()
{
GtkWidget* tmp = gtk_source_view_new();
_srcset.push_back(tmp);
gtk_notebook_append_page(GTK_NOTEBOOK(_nbook),tmp,gtk_label_new("untitled"));
}
...........................................................................................
void editbook::set_text(const std::string& text)
{
int index = gtk_notebook_get_current_page(GTK_NOTEBOOK(_nbook));
GtkTextBuffer* tbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(_srcset[index]));
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(tbuffer),text.c_str(),-1);
}
Compiles fine. But gives this weird runtime error:
Segementation Fault: return 139
I have traced down the problem to: gtk_text_view_get_buffer(GTK_TEXT_VIEW(_srcset[index]));
NOTE: I am using GtkSourceView instead of GtkTextView, but that may not be a problem because I am gettin the same error when I try GtkTextView.
NOTE: I am using Gtk 2x
NOTE: I am not sure whether to tag this question with C or C++. bec. Gtk+ is a C lib. But I am using C++. So I'll just tag both for now.

The problem in your code could be that the child widget added to GtkNotebook through gtk_notebook_append_page is not visible, try showing the child widget through gtk_widget_show call. Something on these lines :
void editbook::add_page()
{
GtkWidget* tmp = gtk_source_view_new();
_srcset.push_back(tmp);
gtk_widget_show(tmp); //Show the child widget to make it visible
gtk_notebook_append_page(GTK_NOTEBOOK(_nbook),tmp,gtk_label_new("untitled"));
}
When you use gtk_notebook_get_current_page if none of the child widget are visible then it returns -1, which I think might be happening in your case & as index is -1 when you use operator[] which doesn't check for bounds the program crashes. I strongly suggest you use vector::at instead of using operator[] so that you get std::out_of_range exception during run time to indicate the problem. You could use:
void editbook::set_text(const std::string& text)
{
int index = gtk_notebook_get_current_page(GTK_NOTEBOOK(_nbook));
GtkTextBuffer* tbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(_srcset.at(index)));
gtk_text_buffer_set_text(GTK_TEXT_BUFFER(tbuffer),text.c_str(),-1);
}
Hope this helps!

Related

SDL 2 Showing an image on screen via a SpriteManager, getting a pointer break

I'm entirely new to SDL 2 , and I'm hoping to find some help with making my very first proper program for a class in it. We've been provided with some code already for use in this project, which is why I'm not simply using a BlitSurface function to make this solution. If that is indeed the better solution, I'll switch over to that. This is part of a State to be used when the program runs, showing a title image.
I am getting a break error due to a pointer issue in the following code:
void MenuState::Enter()
{
//Is to load the title image used for the State
Sprite* extBackgroundSprite = met_extSystem.met_pointextSpriteManager- >CreateSprite("../assets/Testimage1.bmp" , 0 , 0 , 768 , 1024);
}
Which refers to a Sprite made by a SpriteManager class and CreateSprite function, as seen here:
Sprite * SpriteManager::CreateSprite(const std::string & point_stringFilePath, int point_intX, int point_intY, int point_intWidth, int point_intHeight)
{
auto iter = met_arraypointextTextures.find(point_stringFilePath); //breaks here
if (iter == met_arraypointextTextures.end())
//If the iterator cannot locate the sprite we need in our already loaded memory,
//it needs to be loaded into our map to create pointers
{
SDL_Surface* extSurface = SDL_LoadBMP(point_stringFilePath.c_str());
SDL_Texture* extTexture = SDL_CreateTextureFromSurface(met_pointextRenderer, extSurface);
SDL_FreeSurface(extSurface);
met_arraypointextTextures.insert(std::pair<std::string, SDL_Texture*>(point_stringFilePath, extTexture));
iter = met_arraypointextTextures.find(point_stringFilePath);
}
//Creates the sprite, adds a new index point via pushback
Sprite* extSprite = new Sprite(iter->second, point_intX, point_intY, point_intWidth, point_intHeight);
met_arraypointextSprites.push_back(extSprite);
return extSprite;
}
I hope this is enough information and code to present my problem. If not, let me know! And thank you in advance.
Turns out the issue was impossible to solve with the information I provided. The pointer did indeed need to be initialized, but with arguments found in the constructor, which I had not provided here.

C/C++ string memory allocation

I've just recently begun with C/C++ development on an embedded system (ARM - STM32F4 to be more specific) and I am now having almost classical problems of someone who isn't used to C or low level memory managment.
Basically I have a class MenuOption that inherits some field from some other class and basically looks like this:
...
char text[20];
...
void MenuOption::setText(const char* text1)
{
clearCurrent();
needsUpdate = true;
strncpy(text, text1, 20);
width = font->FontWidth*strlen(text);
}
The constructor for this class calls that setText method to store the text. This works fine if I use it like this inside a main function:
std::vector<MenuOption *> mainMenuOptions;
MenuOption* op1 = new MenuOption(13, 15, "Info", WHITE, BLACK);
op1->setSelected(true);
mainMenuOptions.push_back(op1);
But it fails when I want to use it like this:
std::vector<MenuOption *> options;
for (int i = 0; i < things.size(); i++)
{
Thing *th = things[i];
... do some stuff with th ...
MenuOption* op = new MenuOption(190, 38+25*i, "test", WHITE, BLACK);
options.push_back(op);
}
This fails (debugger sort of stalls) at the MenuOption* op ... line. Now I am guessing that this isn't something that I should be doing. But I can't seem to find a working solution.
EDIT:
To answer everyones questions. This does in fact compile with a C++ compiler. GCC using C++11 dialect.
There is a reason why I am using C strings instead of std::string. I am using a few C libraries that need C strings. And whenever I tried to convert that string into a C string inside a FreeRTOS task the thing would fail. The same problem as now actually.
No other breakpoint inside the task will trigger after it reaches that constructor line. I can't step in or skip a line or anything like that at that line. I have a feeling it gets caught by a hard_fault interrupt handler. Other tasks would continue to run. That's the problem. There are no errors or anything that would point me to the cause. The same problem was when I was using std::string when I tried to create a new MenuOption inside a FreeRTOS task. The thing works if I remove the string from the constructor. So I am guessing that it has something to do with strings.
As for string length. I know that strings used here will not be longer than 15 characters. I used those 5 characters for pure "backup"-
As for the ... do some stuff with th ... that was just this: th->flag = true;. I didn't do anything more with it because of this problem.
The tip posted in the comments by Étienne was actually what lead me to the answer. More specifically I found this: http://www.freertos.org/FreeRTOS_Support_Forum_Archive/October_2013/freertos_Using_C_std_vector_in_task_93928e86j.html
void *operator new(size_t size)
{
void *p;
if(uxTaskGetNumberOfTasks())
p=pvPortMalloc(size);
else
p=malloc(size);
return p;
}
void operator delete(void *p)
{
if(uxTaskGetNumberOfTasks())
vPortFree( p );
else
free( p );
p = NULL;
}

Segmentation fault when testing migrated library from qt4 to qt5

I am testing this library but I am getting a segmentation fault whenever it reachs a certain line (the commented one below). This issue comes from this question - tldr the same problem on a much bigger project, so I decided to test the libraries separatedly and apparently this is what fails. This code works on a co-worker's 32bits machine using Qt4 (he handed me the code). I migrated it to Qt5 and compiled with a 32bit compiler and I am getting the segmentation fault. If I comment the offending line and the two below it the program runs (although its just an empty window).
What could be happening?
#include "qenctest.h"
#include <QLibrary>
#include <QtWidgets/QMessageBox>
typedef void (*encRefresh)(QPainter*);
encRefresh enc_refresh = NULL;
typedef void (*encResize)(QSize);
encResize enc_resize = NULL;
typedef QENCSignaler* (*encInit)(QString);
typedef void (*encOpenFile)(QString);
QENCTest::QENCTest(QWidget *parent, Qt::WindowFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
QLibrary _qenc("qenc");
encInit enc_init;
encOpenFile enc_openFile;
enc_init = (encInit) _qenc.resolve("init"); // I checked and it does load the library and the symbol succesfully
enc_openFile = (encOpenFile) _qenc.resolve("openFile");
enc_resize = (encResize) _qenc.resolve("resize");
enc_refresh = (encRefresh) _qenc.resolve("refresh");
QString path = "encfg";
QENCSignaler* qencSignaler = enc_init(path); // Throws segfault here
connect(qencSignaler, SIGNAL(newChart(Chart*)), this, SLOT(qencNewChart(Chart*)));
connect(qencSignaler, SIGNAL(startReadChart(char*)), this, SLOT(qencStartReadChart(char*)));
enc_openFile("PL2BAPOL.000");
int _s = 0;
}
Debug info:
PS: What does it mean that some locals & expressions are in red?
EDIT
Alright, the only major changes I had to make in the library code were these:
AttributeSet::iterator vItPOI = attributes.at(i).find("POI");
if (vItPOI == attributes.at(i).end()) continue;
AttributeSet::iterator vItPOI0 = attributes.at(i).find("POI0");
if (vItPOI0 == attributes.at(i).end()) continue;
if (vItPOI -> getStringValue() == "Bankowoæ" &&
selectedPOI & POI_BANKING) {
if (vItPOI0 -> getStringValue() == "Placówka banku") {
drawSymbol(painter, x, y, POI_BANKING);
}
}
To this (there are more ifs but this illustrates it properly)
ShapeAttribute vItPOI = attributes.at(i).find("POI").value();
if (attributes.at(i).find("POI") == attributes.at(i).end()) continue;
ShapeAttribute vItPOI0 = attributes.at(i).find("POI0").value();
if (attributes.at(i).find("POI0") == attributes.at(i).end()) continue;
if (vItPOI . getStringValue() == "Bankowo��" &&
selectedPOI & POI_BANKING) {
if (vItPOI0 . getStringValue() == "Plac�wka banku") {
drawSymbol(painter, x, y, POI_BANKING);
}
}
In theory it should be the same shouldnt it? Although I do find strange that in the first snippet it uses -> instead of . when its not a pointer. I had to change it to that because I was getting these errors:
^
..\qenc\ShapeLandPOI.cpp: In member function 'virtual void ShapeLandPOI::draw(QPainter*)':
..\qenc\ShapeLandPOI.cpp:74:62: error: conversion from 'QMap<QString, ShapeAttribute>::const_iterator' to non-scalar type 'QMap<QString, ShapeAttribute>::iterator' requested
AttributeSet::iterator vItPOI = attributes.at(i).find("POI");
^
..\qenc\ShapeLandPOI.cpp:76:64: error: conversion from 'QMap<QString, ShapeAttribute>::const_iterator' to non-scalar type 'QMap<QString, ShapeAttribute>::iterator' requested
AttributeSet::iterator vItPOI0 = attributes.at(i).find("POI0");
^
In your changed code you have the line
ShapeAttribute vItPOI0 = attributes.at(i).find("POI0").value();
But if "POI0" is not found the find function would return end which is an iterator pointing to beyond the collection, and so it's value function would be causing undefined behavior.
As for the errors it seems that the QMap object is constant, and so you can't get non-const iterators. Just change to use AttributeSet::const_iterator instead and you can use the original function otherwise unmodified. This will probably fix your crashes, as then you don't have the risk of undefined behavior as described above.

How to iterate through every QSpinBox in QGridLayout

I have the following problem. I'm using Qt in the newest version 5.2 and in my code I have 11QSpinBox. Every in QGridLayout. I want to iterate through every QSpinBox in this layout and set value that I read from file. When I'm using:
ui.QSpinBox->setValue()
is everything ok, but the code looks too long.
I tried using:
static_cast<QSpinBox*>(ui.gridLayout->itemAtPosition(1,1)->widget())->setValue(100);
but I get exception Access violation and MS VS2010 show me this function in qatomic_mscv.h:
inline bool QAtomicOpsBySize<4>::deref(long &_q_value) Q_DECL_NOTHROW
{
return QT_INTERLOCKED_DECREMENT(&_q_value) != 0;
}
So i thought about not using pointer to QSpinBox but an object:
static_cast<QSpinBox>(ui.gridLayout->itemAtPosition(1,1)->widget()).setValue(100);
but it didn't change the value. Any exception didn't occur.
OK, I used even dynamic_cast with pointer type and I got again access Violation but this time VS2010
point me to qscopedpointer.h:
inline T *data() const
{
return d;
}
It happens for qobject_cast too.
I'm sure that position point to QSpinBox. What I'm doing wrong?
Consider using qFindChildren instead:
QList<QSpinBox*> spinBoxen = ui.findChildren<QSpinBox*>();
Q_FOREACH(QSpinBox *spinBox, spinBoxen) {
// do something to do the spinBox
}

segfault when trying to access a string member of a class

I have a class Message that has a std::string as a data member, defined like this:
class Message
{
// Member Variables
private:
std::string text;
(...)
// Member Functions
public:
Message(const std::string& t)
: text(t) {}
std::string getText() const {return text;}
(...)
};
This class is used in a vector in another class, like this:
class Console
{
// Member Variables
private:
std::vector<Message> messageLog;
(...)
// Member Functions
public:
Console()
{
messageLog.push_back(Message("Hello World!"));
}
void draw() const;
};
In draw(), there's an iterator that calls getText(). When it does, the program segfaults. I've determined that text is valid inside the Message constructor. However, I can't tell if it's valid from inside Console. I'm assuming it is, but if I try to inspect indices of Console's messageLog, gdb tells me this:
(gdb) p messageLog[0]
One of the arguments you tried to pass to operator[] could not be converted to what
the function wants.
Anyone know what's going on?
EDIT: here's draw(). TCODConsole is part of a curses library I'm using, and so this function prints each message in Console to a part of the curses screen. TL and BR are Point member objects (two ints) that tell where on the screen to draw Console. I left out parts of Message and Console in the original question to hopefully make things clearer, but if you need me to post the entire classes then I can. They aren't too long.
void Console::draw() const
{
int x = TL.getX(), y = TL.getY();
int width = BR.getX() - TL.getX();
int height = BR.getY() - TL.getY();
// draw the Console frame
TCODConsole::root->printFrame(x, y, width, height, true);
// print the Console's messages
vector<Message>::const_iterator it;
for(it=messageLog.begin(); it<messageLog.begin()+height-1; ++it)
{
string message = "%c" + it->getText();
TCODConsole::setColorControl(TCOD_COLCTRL_1,
it->getForeColor(),
it->getBackColor());
y += TCODConsole::root->printRectEx(x, y, width, height,
TCOD_BKGND_NONE,
TCOD_LEFT,
message.c_str(),
TCOD_COLCTRL_1);
}
}
My guess is that by the point you use it->getText(), the iterator is NULL. Add a check it != messageLog.end() when you walk the array, and before calling it->getText().
Is it definitely std::vector messageLog and not std::vector<Message> messageLog? That seems a bit odd.
What does the height have to do with the vector's index? You have:
messageLog.begin()+height-1;
Why are you adding the screen coordinate to the iterator? That seems to be your problem and you're most likely overindexing and that's why you're getting a SIGSEGV.
What you probably want is to simply iterate over all the messages in the vector and display them at a particular location on the screen. I see what you're trying to do, but if you're trying to calculate the screen boundary using the iterator you're definitely going about it the wrong way. Try running a counter or get messageLog.size() and then recalculate the height with each iteration. As for the loop just do:
for(it=messageLog.begin(); it!=messageLog.end(); ++it)
It's probably because the scope of the Message object created in the Console method is just the Console method. So, if your program is trying to access this object in another method, like draw, you will get this segmentation fault, since this object is deleted after the execution.
Try this (just insert a new keyword):
Console()
{
messageLog.push_back(new Message("Hello World!"));
}
In this case, the object is not deleted after Console's end.
Just remember to delete the objects created when your program doesn't need them anymore.