I try to learn more about programming by studying open source using
UML. The code I have found is in the stage between Qt 3 and Qt 4.
The project is not that active so I ask this question here. Maybe
I should add that the program using this code do run.
Note, I am a junior. I ask because I want to learn.
My question is simple:
Do this code leak memory?
If not, why ?
void warn(const QString & s) {
// not showed dialog to compute needed size
QDialog d_aux;
Q3VBoxLayout * vbox_aux = new Q3VBoxLayout(&d_aux);
vbox_aux->setMargin(5);
Q3TextEdit * e = new Q3TextEdit(&d_aux);
e->setText(s);
// showed dialog
QDialog * d = new QDialog;
d->setCaption("My caption");
Q3VBoxLayout * vbox = new Q3VBoxLayout(d);
vbox->setMargin(5);
Q3TextView * t = new Q3TextView(d);
QFontMetrics fm(QApplication::font());
int maxw = (MyWindow::get_workspace()->width() * 4) / 5;
int maxh = (MyWindow::get_workspace()->height() * 4) / 5;
int he = (e->lines() + 5) * fm.height();
t->setText(s);
t->setMinimumSize(maxw, (he > maxh) ? maxh : he);
vbox->addWidget(t);
d->show();
}
Thanks // JG
You have one: The QDialog * d = new QDialog; The other pointers got a parent instance which takes ownership of the pointers. (Please confirm it in the documentation of Q3VBoxLayout, Q3TextEdit and Q3TextView)
I think you are leaking memory, but it would be simple to verify with a program like valgrind on Linux and so on. Let us see what dynamic memory allocations you do in your function:
Q3VBoxLayout * vbox_aux = new Q3VBoxLayout(&d_aux);
That is alright because it gets a parent. Let us see the next:
Q3TextEdit * e = new Q3TextEdit(&d_aux);
That is also alright for the same reason above. Let us see the next:
QDialog * d = new QDialog;
Here, you problems begin to arise because the dialog does not have a parent. You have several ways of fixing it.
1) Assign a parent, although this might not be ideal in this case as you do not seem to have any parent'ish look in your code for this widget. That is, nothing that could really become the parent of it unlike your Qt application if you are using that. This fix may require some major rework depending on the whole context that you have shown.
2) Use a smart pointer, e.g. QPointer around it, so it will be managed for you automatically. That should have been available at the age of the code you are using. This may also need some code rework depending on more context that you have not provided.
Let us see the next dynamic memory allocation:
Q3VBoxLayout * vbox = new Q3VBoxLayout(d);
That is alright for the reasons mentioned before. Let us see the next and last:
Q3TextView * t = new Q3TextView(d);
That is also alright for the reasons mentioned before.
Related
I am attempting to write multiple nodes in a single request, however I have not found any documentation or examples on how to do that, every time I find anything regarding the issue, a single node is written. Based on my understanding of the open62541 library (which is not much), I've attempted to do this like so:
void Write_from_3_to_5_piece_queue() {
char NodeID[128];
char NodeID_backup[128];
char aux[3];
bool bool_to_write = false;
strcpy(NodeID_backup, _BaseNodeID);
strcat(NodeID_backup, "POU.AT2.piece_queue["); // this is where I want to write, I need only to append the array index in which to write
UA_WriteRequest wReq;
UA_WriteValue my_nodes[3]; // this is where I start to make things up, I'm not sure this is the correct way to do it
my_nodes[0] = *UA_WriteValue_new();
my_nodes[1] = *UA_WriteValue_new();
my_nodes[2] = *UA_WriteValue_new();
strcpy(NodeID, NodeID_backup);
strcat(NodeID, "3]"); //append third index of array (will write to piece_queue[3])
my_nodes[0].nodeId = UA_NODEID_STRING_ALLOC(_nodeIndex, NodeID);
my_nodes[0].attributeId = UA_ATTRIBUTEID_VALUE;
my_nodes[0].value.hasValue = true;
my_nodes[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
my_nodes[0].value.value.storageType = UA_VARIANT_DATA_NODELETE;
my_nodes[0].value.value.data = &bool_to_write;
strcpy(NodeID, NodeID_backup);
strcat(NodeID, "4]");
my_nodes[1].nodeId = UA_NODEID_STRING_ALLOC(_nodeIndex, NodeID);
my_nodes[1].attributeId = UA_ATTRIBUTEID_VALUE;
my_nodes[1].value.hasValue = true;
my_nodes[1].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
my_nodes[1].value.value.storageType = UA_VARIANT_DATA_NODELETE;
my_nodes[1].value.value.data = &bool_to_write;
strcpy(NodeID, NodeID_backup);
strcat(NodeID, "5]");
my_nodes[2].nodeId = UA_NODEID_STRING_ALLOC(_nodeIndex, NodeID);
my_nodes[2].attributeId = UA_ATTRIBUTEID_VALUE;
my_nodes[2].value.hasValue = true;
my_nodes[2].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
my_nodes[2].value.value.storageType = UA_VARIANT_DATA_NODELETE;
my_nodes[2].value.value.data = &bool_to_write;
UA_WriteRequest_init(&wReq);
wReq.nodesToWrite = my_nodes;
wReq.nodesToWriteSize = 3;
UA_WriteResponse wResp = UA_Client_Service_write(_client, wReq);
UA_WriteResponse_clear(&wResp);
UA_WriteRequest_clear(&wReq);
return;
}
At first I didn't have much hope that this would work, but it turns out this actually writes the values that I wish. The problem is that on UA_WriteRequest_clear(&wReq); I trigger an exception in the open62541 library:
Also, I know I can write multiple values to arrays specifically, even though in this particular example that would fix my issue, that's not what I mean to do, this example is just to simplify my problem. Just suppose I have a multi-type structure and I want to write to it, all in a single request. I appreciate any help!
First of all, this is bad:
UA_WriteValue my_nodes[3];
my_nodes[0] = *UA_WriteValue_new();
my_nodes[1] = *UA_WriteValue_new();
my_nodes[2] = *UA_WriteValue_new();
my_nodes is already created on the stack, and then you are copying the content of a new object into it by dereferencing. This definitely leads to memory leaks. You probably want to use UA_WriteValue_init() instead.
Never ever dereference the return value of a new() function.
Let's go bottom up:
UA_WriteRequest_clear(&wReq) is recursively freeing all content of the wReq steucture.
This means that it will also call:
UA_Array_delete(wReq.nodesToWrite, wReq.nodesToWriteSize, ...)
which in turn calls UA_free(wReq.nodesToWrite)
And you have:
wReq.nodesToWrite = my_nodes;
with
UA_WriteValue my_nodes[3];
This means that you are assigning a variable, which lives on the stack to a pointer, and later this pointer is freed. free can only delete stuff which is on the heap and not stack, and therefore it fails.
You have two options now:
If you still want to use the stack trick the UA_clear in thinking that the variable is empty:
wReq.nodesToWrite = NULL;
wReq.nodesToWriteSize = 0;
UA_clear(&wReq);
Put the nodes on the heap:
Instead of
UA_WriteValue my_nodes[3]; use Something like UA_WriteValue *my_nodes = (UA_WriteValue*)UA_malloc(sizeof(UA_WriteValue)*3);
Also I strongly recommend that you either use valgrind or clang memory sanitizer to avoid all these memory issues.
Iam trying to highlight some words inside a PDF, I searched on a good C++ library for doing this, I found MuPDF, I download the last version and compiled it.
Now iam starting to write some codes to highlight the text in the PDF, there is no examples for this task in c++, so I start to try myself.
fz_document *doc;
fz_context *ctx;
ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
fz_register_document_handlers(ctx);
doc = fz_open_document(ctx, "D:/b.pdf");
cout << fz_count_pages(ctx, doc) << endl;
fz_page *page = fz_load_page(ctx, doc, 0);
fz_quad *q;
fz_search_page(ctx, page, "more", q, 1);
fz_rect rec = fz_rect_from_quad((*q));
fz_stext_page *pp = fz_new_stext_page(ctx, rec);
fz_point point;
point.x = 0;
point.y = 0;
fz_highlight_selection(ctx, pp, point, point, q, 16);
fz_buffer *buffer = fz_new_buffer_from_stext_page(ctx, pp);
fz_save_buffer(ctx, buffer, "D:/Final.pdf");
That is what i tried so far iam not sure it crash at a point, iam using it with Qt 5.13 MSVC 2017, so what i did wrong, or if some one has a good useful example to do this or for the library in general as it leak examples so far from my search, all the examples are in python, java, and other put for c++ there is few examples just 2 examples coming with the library.
Even if there is another good c++ library has this function please share it.
Thanks in advance.
So it seems you are making the common newbie error of thinking that just because an API uses a pointer, you must declare a pointer. But that is not correct, instead you should declare an object and pass the address of that object. So for example this
fz_quad *q;
fz_search_page(ctx, page, "more", q, 1);
fz_rect rec = fz_rect_from_quad((*q));
should actually be this
fz_quad q; // object not pointer
fz_search_page(ctx, page, "more", &q, 1); // address of the object to get the pointer
fz_rect rec = fz_rect_from_quad(q);
The idea is that fz_search_page will fill in the fz_quad object. Your version fails because you gave an uninitialised pointer to fz_search_page which will result in memory corruption when fz_search_page tries to use that pointer.
You should also definitely add the sanity check
doc = fz_open_document(ctx, "D:/b.pdf");
if (doc == nullptr) // check if we can open the document
{
std::cerr << "cannot open document\n"; // or whatever error handling you prefer
exit(1);
}
Opening files or documents can fail for all sorts of reasons and you should always check that it works.
There's probably lots else that needs improving but those issues stood out for me.
To elaborate on john's answer, you need to allocate space for the results, not just a pointer. This can be stack allocated.
fz_quad q[100]; // stack allocate array of 100 quads
int n = fz_search_page(ctx, page, "more", q, 100);
However, there seem to be some more areas of confusion as to what the APIs actually do.
The fz_search_page function returns a list of quads covering the search hits. fz_highlight_selection also returns a list of quads but this time based on the location on a page a user has dragged using the start and end coordinates of the selection.
fz_new_buffer_from_stext_page returns a plain text version of the structured text data. This is NOT in PDF format.
If you want to add a highlight annotation, then you should create a highlight annotation covering the area you want highlighted:
n = pdf_search_page(ctx, page, "more", q, 100);
if (n > 0) {
pdf_annot *annot = pdf_create_annot(ctx, page, PDF_ANNOT_HIGHLIGHT);
for (i = 0; i < n; ++i)
pdf_add_annot_quad_point(ctx, annot, q[i]);
pdf_update_annot(ctx, annot);
}
Then you can save the new modified PDF document:
pdf_save_document(ctx, doc, "out.pdf", NULL);
I'm a novice to use c++ and morely qt. I've developed a multi-class software to calculate easter date. Now i'd like to write it to a label on button click, but i get a -i think- segmentation fault. My code is this -just a function, but please, ask if you want to see other parts-:
void MainWindow::on_btn_calcola_clicked()
{
Easter *e;
int anno = ui->text_anno->text().split(" ")[0].toInt();
int *date = e->dataPasqua(anno);
int giorno = date[0];
int mese = date[1];
QString d = QString::number(giorno);
QString m = QString::number(mese);
QString dataCompleta = d+"/"+m;
ui->lbl_result->setText(dataCompleta);
}
What's wrong? Thankyou so much!
Variable "e" is declared, but not initialized.
Possible solution is to use "make_unique" or simple new operator, like:
e = new Easter();
Tried a declaration like below for Easter object.
(Is better to avoid pointer when is not needed)
Easter e = Easter();
And in a second time, try to return a QList instead of a pointer in your function dataPasqua()
Is the two potential issues, the rest seems to be ok.
I am still relatively new to Qt and I have recently been working on a large project. When I attempt to run the project I get this error:
ASSERT failure in QList<T>::at: "index out of range", file c:\qt\qt5.3.0\5.3\msvc2013_64\include\qtcore\qlist.h, line 479
Just wondering if anyone knows what this means or how I might go about tracking down the source of the problem?
[edit] I believe that the addition of this code is causing the error
autAtom *aP = new autAtom(Principal);
autAtom *aQ = new autAtom(Principal);
autData *P = new autData (DataAtom, aP);
autData *Q = new autData (DataAtom, aQ);
autData *X = new autData (AnyData);
AUTPostulate *p;
autStatementList preList;
{
preList.clear();
//autData *d1 = new autData(NotHereData, X);
autStatement *pre1 = new autStatement(aP, believes, X);
autStatement *goal = new autStatement(aP, sees, X);
preList.append(pre1);
p = new AUTPostulate("BS", BS, goal, preList);
cout << "" << p->getString().toStdString() << endl;
AUTPostulates.append(p);
}
When this is taken out the tool runs fine.
I ran into a similar issue because I did a connect on itemChanged before populating the widget and then while populating my slot code was called. After I put in a guard that prevented signal handling during widget population, I found I could populate the widget fine and I could also handle the signal fine after. Hope this helps.
Index out of range means you're trying to access an index of a QList object, or maybe an object that is a subclass of a QList that does not exist. So if you have a QList with a length of 5 and you try to access index 5, it will be out of range.
Also, it looks like your code contains a lot of classes that are not standard to Qt or C++. At least I don't recognize them. It's difficult to say what's going on here without knowing about those classes.
I wonder could anyone be of help.
If for example I wanted to use the output of the QEasingcurve for another purpose other than driving a QAnimation, is this possible? For example, if I had a numerical read out on my GUI that I wanted to grow, overshoot and bounce back into place could I use the QEasingcurve for this purpose?
I have used Qt for quite a while but have never dabbled with any of these parts of it - I am trying to work it out but cannot, so thought I'd ask here.
I am not sure I understand correctly what you want to display, but from what I understand, using QPropertyAnimation is probably the way to go.
However, to answer your question, you can of course use QEasingCurve in a standalone manner, you just need to use the valueForProgress(qreal progress) member function.
Hey - Just wanted to update with how I carried this out in case anyone looks it up in the future.
void RPM::updateGauge(float speed)
{
easing = new QEasingCurve(QEasingCurve::OutElastic);
easing->setAmplitude(1.0);
currentPosition = (float)ui->svgdial_currentSpeed->value();
newPosition = speed;
difference = newPosition - currentPosition;
interval = 0.0;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(doGaugeMovement()));
timer->start(60);
}
void RPM::doGaugeMovement()
{
interval+=0.01;
ui->svgdial_currentSpeed->setValue(currentPosition + ( difference * easing-
>valueForProgress( interval ) ) );
if(interval >= 1.0)
{
timer->stop();
}
}
Simply used a timer to update the gauge slowly, pulling the valueForProgress result for its new position each time.