|
And save us some as well.
|
|
|
|
|
Amen!
"In testa che avete, Signor di Ceprano?"
-- Rigoletto
|
|
|
|
|
OK, another inherited code and I am not sure how it works...
I am using this to process "system commands" - Linux.
It works as expected with
command = "hcitool dev"
now I need to use
"sudo hcitool info (address) "
and it fails
it also fails with just
"sudo"
The failing code is this :
if(QP->waitForReadyRead() | QP->waitForFinished())
{
#ifdef TASK_PROCESS_COMMAND
text = "SUCCESS waitForReadyRead ";
text += " real time ";
text += " elapsed time ";
text += QString::number(QET->elapsed());
text += " mS ";
qDebug() << text;
#endif
}
else
{
text = "FAILED waitForReadyRead ";
text += " real time ";
text += " elapsed time ";
text += QString::number(QET->elapsed());
text += " mS ";
qDebug() << text;
}
Here is my passed to /bin/sh code
QP->start("/bin/sh", QStringList() << "-c" << command);
The way I interpret the error
there is no response to "sudo"
and I do not understand why.
|
|
|
|
|
This is clearly a nix question, not a C/C++ one, but since you asked:
Try executing from a terminal a command like:
>sudo ls
and see what happens. You will probably be prompted to enter a sudo password. Obviously that cannot happen if you issue the command from a shell without an input file.
The whole purpose of sudo command is to allow only certain users (sudo-ers) to change important settings. The way it verifies that, is by asking for password. Password is cached for a few minutes. You can find many more details in the sudo man page[^].
Mircea
|
|
|
|
|
We keep telling you, QT is not within the scope of this forum. If you're going to continue posting questions, at least rephrase them as non QT C++
As such, you could rewrite your sudo problem as follows
#include <cstdio>
int main()
{
system("sudo ps");
}
Now, either you'll have sudo set up to allow you to run commands without a password, in which case you should get a process list back, or you will be prompted for a password. My guess is that sudo is trying to prompt for a password, but whatever QT is doing, you never see the password prompt. Or maybe if you look at an attached terminal or wherever stdout gets sent to, you'll find the password prompt there.
I'd suggest you compile this very simple program and try it from a command line. If it prompts for a password, then you know what the issue is. If it works, then you probably need to ask on a QT forum, as it would seem the issue is something that QT is doing. For all we know QT intercepts sudo requests and handles them differently.
Note that the parameter to the system call is just "sudo ps" , you don't need to specify the shell to use, sudo will use some default shell, probably the shell named in /etc/passwd as the user's shell. But there may be a way to override that. I'm just feeling too lazy to dig into the sudo docs
Addionally, assuming you need the output from hci info , the system() call is not a good choice. To capture the output, you'd need to redirect stdout to a file, then read that file back in to examine the output. Much better would be to use popen() . Or since you're using QT, then maybe QProcess would be a better fit. There's a quick example of how to do this here : https://stackoverflow.com/a/19413789
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
Most if not all of what I said the last time you posted about sudo still applies.
Re: Please - explain the C++ code / function - C / C++ / MFC Discussion Boards[^]
Before following up with this or anything in the future at a minimum you need to understand what the command does, including the exact output when you run it yourself from the command line.
You also need to understand everything the QT QProcess class does.
QProcess Class | Qt Core 6.6.1[^]
You must specifically understand how to code to all of the following
- exitCode()
- readAllStandardError()
- readAllStandardOutput()
- There must be a way to control stdin dynamically but I could not see it. But you can use setStandardInputFile() for basic understanding.
I suggest you start with the command 'ls' and do NOT start with 'sudo' so you can understand how to use the above methods. You should test the following
- A directory that does not exist
- A directory that does exist.
Keep in mind that although you are working with the QT library coding to run a process in ANY programming language is going to require that you understand the dynamics of how that works. It might help to read up on what the following means.
- Exit value
- stdio: stderr, stdout, stdin.
|
|
|
|
|
Hi, I'm working on implementing a concurrent queue (implemented as single linked list) and I've encountered a problem. The structure of my linked list node looks like this:
struct queue {
queue *head, *tail;
pthread_mutex_t head_mut, tail_mut;
}
struct node {
_Atomic(node*) next;
int item;
};
I am currently implementing pop and push operations, both of them have their own separate mutex - tail_mut and head_mut respectively.
The list always includes a dummy node at the beginning.
I'm encountering an issue when there's only one element in the list (the dummy node plus this one element). I can't figure out how to handle the case where one thread is trying to push an element and another is trying to pop an element from the list.
The problem arises when we perform a pop operation first and change the head to head->next. In this scenario, another thread can still push elements to the list by adding them to the end of the list (tail). However, the list has only one element (the one that is being popped = tail), so i must find a solution to somehow block this operation or to signal 'pushing' thread that it should push to the head not to tail.
Acquiring the tail mutex would obviously solve the problem, but I'm looking for a potentially more efficient solution (so I would not block push operations by acquiring the tail mutex).
Is there a more efficient way to handle this situation? Any suggestions would be greatly appreciated.
|
|
|
|
|
cod3Ninj4 wrote: I can't figure out how to handle the case
Good thing because there is no way to handle that case.
You can only do it with one of the following.
1. One and only one lock.
2. Two dummy nodes, one at each end.
cod3Ninj4 wrote: Is there a more efficient way to handle this situation?
Probably but that answer depends on how it is used and not on how it is implemented.
|
|
|
|
|
I am taking Harvard's CS50 class. We are learning C.
They use their own library where you include cs50.h.
There is a function called get_string that returns a string.
I think it has a memory leak.
I think this is the source code:
https://github.com/cs50/libcs50/blob/main/src/cs50.c
They are saying stuff like:
string name = get_string("What is your name?");
Then, they never call free on the memory in main.
Anyone know how the memory gets freed or if it is a leak?
Thanks.
|
|
|
|
|
No.
From the very code you linked to:
static void teardown(void)
{
if (strings != NULL)
{
for (size_t i = 0; i < allocations; i++)
{
free(strings[i]);
}
free(strings);
}
}
The library keeps track of all the strings it allocates and frees them when your app exits.
|
|
|
|
|
After Dave's on-point answer, this is just a general comment with the hope that your question becomes a teachable moment.
Way back when, as I was learning programming, I came up with a saying: "the silly is on the other side of the screen". It obviously can be interpreted both ways, but the idea is to look where the balance of probability indicates that the error should be. In my case, I learned my first assembly language trying to prove that the compiler was wrong - of course it wasn't. In your case, the chance that a course from a prestigious institution contains a trivial error are rather small compared with the chance that you are missing something.
Try to find what you are missing and those "Aha!" moments may benefit you more than the rest of the assignment. And, when in doubt, try to remember: the silly is on the other side of the screen.
Mircea
|
|
|
|
|
This is their pseudocode for bubble sort:
-------------------------------------------------------
Repeat n-1 times
For i from 0 to n–2
If numbers[i] and numbers[i+1] out of order
Swap them
If no swaps
Quit
-------------------------------------------------------
Then, David Malan supposedly analyzed the running time
by multiplying n-1 by n-2.
|
|
|
|
|
That is, indeed, the worst case performance of bubble sort. Bubble sort - Wikipedia[^]. Not sure what you want to say.
Mircea
|
|
|
|
|
What does that have to do with "get_string memory leak"?
|
|
|
|
|
Just the fact that’s not wise to assume the error is someone else’s code. Better to try to understand what’s going on and discover what atexit function does.
Next step would be to eventually figure out that the “constructor” code is contrived and the call to atexit could be done on first allocation.
Edit: not sure to what message was your reply. Stuck to a cell phone today and CP is not the greatest on mobile. Apologies if I’m confusing you.
Mircea
|
|
|
|
|
First the question is about a method that may leak memory, then a sudden jump-cut a post about bubble sort pseudocode, then another jump-cut to your philosophy.
To say I'm confused as to what's going on with this thread is an understatement.
|
|
|
|
|
Apologies again! I thought your message was directed at my answer. Anyway I'll try to cut the philosophy c**p in the future; it's waste of time.
Mircea
|
|
|
|
|
mike7411 wrote: I think it has a memory leak.
Despite the other posts - yes this would be a classic example of a memory leak.
The teardown() method, as used, is pointless. When the application exits (on every modern OS including small ones) the memory that the application uses is returned to the OS. So the fact that teardown is called on the application exit via the atexit() method is absolutely pointless.
If you were to use the code in a regular application, especially but not limited to one that does not exit, then this would fail. Because of memory leaks. You could not call teardown() arbitrarily either because it would clear everything.
Now it is possible that the point of the code is not to teach you efficient memory usage. But one could certainly argue that the get_string() method should make it clear that this is not a good way to do things.
However the following is in comment for that method.
Stores string
on heap, but library's destructor frees memory on program's exit.
And that indicates that the creator of this code did not understand/know what I pointed out above.
The code also has a copyright date of 2023 so there is no claim that the code could have been written, for example 50 years ago, where one might (perhaps) have used an OS where the application would have needed to do that. Note however that even then I am not sure any OSes actually worked that way. Back then PC-DOS, CPM and early unix versions (there was no linux) returned memory to the OS.
You can take from this that you should not write code like this.
In general in C and C++ you should always control the scope of your memory allocations. So for example if your method allocates some memory then that same method should deallocate (all exit conditions for the method included.) There should almost never be a need to have a method return an allocation and if it does happen then the method should document (comment) that the caller is responsible for the allocation.
C++ makes this easier since you can wrap the allocation in a class. And control allocation/deallocation from that. That is something that I would suggest always doing. So in C++ you would never return an allocated pointer.
|
|
|
|
|
You've covered everything I was going to say, and then some. I was not sure what early versions of DOS might have done with allocated memory at program exit, but it's nice to know that even then, an most OS's would do the Right Thing™.
The code looks like it comes from the early 80's. That it should come from a prestigious university (it is that Harvard, right?), that should know better, is disheartening. Although, it might be a shining example of what not to do.
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
Actually, you, like I do, should question the exisitential "being" of said OP, if this is any indication of a sentience which can't be gleened from his reputation due to the fact that there is no access to said: mike7411 - Professional Profile[^]
I know, I know. A kite joke.
|
|
|
|
|
k5054 wrote: That it should come from a prestigious university (it is that Harvard, right?), that should know better
That of course doesn't mean anything.
Large organizations, all large organizations, tend towards the average. That is inevitable due to size.
Besides that there is no determination about an individuals competence in general or for specific things.
You can also google for variations of the code library and find variations. I found a variation that looked like it was C++. No memory leak in that (very brief look) because it was returning 'string'. So possible that someone familiar with C++ but not so much C converted it. And also possible it wasn't even the person teaching the class, just that the teacher found it and is using it.
|
|
|
|
|
Harvard esp. so
Charlie Gilley
“They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759
Has never been more appropriate.
|
|
|
|
|
First - my apology for taking so much space, I promise to delete ALL after I get this solved - unless it is of benefit to forum...
Here is the current status of "main menu with sub menus "
using "connect" with lambda - it works only on FIRST menu.
I believe the sender and subsequent trigger are WRONG.
I am enclosing the code which creates
the " main menus with their associated sub menus ".
The code works as expected / desired.
The issue is using "connect" as a trigger..sub menu selection...
{ for (index = 0; index < list.size(); ++index)
{
{ { subMenu[index] = m_ui->menuWindow_cpntrol;
subMenu[index] = subMenu[index]
->addMenu(list[index] + " # " + QString::number(index));
mainAction[index] = subMenu[index]->menuAction();
subSize = list_array[index].size();
for (index_sub = 0; index_sub < subSize; ++index_sub)
{ { { subAction[index_sub]= subMenu[index]->addAction(list_array[index][ index_sub] + " #" + QString::number( index_sub));
subAction[index_sub]->setCheckable(true);
} } } }
QAction* tempAction = new QAction(); tempAction->setCheckable(true);
{ }
{ {
} }
{
{}
} } }
{
}
}
Here is my current, working with FIRST menu code.
I do apology for "debug" junk code , it is a little hard to follow the real code.
{
#ifdef LAMBDA
text = "START TASK DEBUG lambda ... ";
text += Q_FUNC_INFO;
text += QString::number(__LINE__);
qDebug() << text;
#endif
int submenu_index = -1;
int mainmenu_index= -1;
QString mainMenu;
QObject obj;
qDebug() << " index_sub " << index_sub ; obj.connect(subMenu[index_sub],&QMenu::triggered,subMenu[index_sub ],[](QAction* action)
{
QString path=action->text();
#ifdef LAMBDA
qDebug() << "TEST need index ?? " << path;
qDebug()<<"path (sub menu trigger ) "<< path ;
#endif
QWidget* parent=action->parentWidget();
path = QString("(%1)").arg(parent->actions().indexOf(action));
#ifdef LAMBDA
qDebug()<<"path (sub menu ) with index TOK "<< path ;
#endif
while(parent)
{
QMenu* menu=qobject_cast<QMenu*>(parent);
QString title=menu->title();
#ifdef LAMBDA
qDebug()<<"title (main menu ) "<< title ;
#endif
path+="->"+title;
qDebug()<<"path (title) "<< path ;
parent=parent->parentWidget();
#ifdef LAMBDA
qDebug()<<"TRACE while first entry crasher ... "<< __LINE__ ;
#endif
if(parent)
{
#ifdef LAMBDA
qDebug()<<"TRACE parent widget (??) valid continue ... "<< __LINE__ ;
#endif
QMenu* menu=qobject_cast<QMenu*>(parent);
#ifdef LAMBDA
qDebug()<<"TRACE parent widget main menu (??)continue "<< __LINE__ ;
#endif
int index=0;
const QList<QAction*> actions=menu->actions();
#ifdef LAMBDA
qDebug()<<"TRACE parent widget main menu list (actions) continue "<< __LINE__ ;
#endif
for(const QAction *act : actions)
{
#ifdef LAMBDA
qDebug()<<"TRACE for(const QAction *act : actions) "<< __LINE__ ;
#endif
#ifdef LAMBDA
qDebug()<<"TRACE title (??) " << title << __LINE__ ;
#endif
#ifdef LAMBDA
qDebug()<<"TRACE act->text()==title "<< act->text() << __LINE__ ;
#endif
if(act->text()==title)
{
#ifdef LAMBDA
qDebug()<<"TRACE main menu found act->text()==title "<< act->text() << __LINE__ ;
#endif
path = QString("(%1)").arg(index);
#ifdef LAMBDA
#endif
#ifdef LAMBDA
qDebug()<<"HERE path (main menu -> sub menu) "<< path ;
#endif
goto TEMP_LABEL;
}
#ifdef LAMBDA
qDebug()<<"TRACE "<< __LINE__ ;
#endif
index++;
}
}
} TEMP_LABEL: qDebug()<<" FINAL (??) "<< path;
} );
QString::number(__LINE__);
#ifdef LAMBDA
text = "END TASK DEBUG lambda... ";
text += Q_FUNC_INFO;
text += QString::number(__LINE__);
qDebug() << text;
#endif
return 0;
}
'
Here is more junk - actual debug output when first "main menu" and its "first sub menu " is selected - by triggering on first sub menu.
19:53:10: Starting /mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/mdi/mdi...
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
"START TASK DEBUG lambda ... int MainWindow_Bluetooth::setupLambda()89"
index_sub 0
"END TASK DEBUG lambda... int MainWindow_Bluetooth::setupLambda()213"
TEST need index ?? "SubWindow LOCAL terminal all options #0"
path (sub menu trigger ) "SubWindow LOCAL terminal all options #0"
path (sub menu ) with index TOK "(0)"
title (main menu ) "terminal # 0"
path (title) "(0)->terminal # 0"
TRACE while first entry crasher ... 138
TRACE parent widget (??) valid continue ... 143
TRACE parent widget main menu (??)continue 149
TRACE parent widget main menu list (actions) continue 154
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "Tile subwindows " 169
TRACE 194
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "Cascade subwindows " 169
TRACE 194
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "Maximize current subwindow " 169
TRACE 194
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "" 169
TRACE 194
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "" 169
TRACE 194
TRACE for(const QAction *act : actions) 163
TRACE title (??) "terminal # 0" 166
TRACE act->text()==title "terminal # 0" 169
TRACE main menu found act->text()==title "terminal # 0" 175
HERE path (main menu -> sub menu) "(5)"
FINAL (??) "(5)"
19:53:27: /mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/mdi/mdi exited with code 0
Here is the failure when ANY main menu , with exception of first one , is used.
That points to probable cause - wrong sender....
19:31:40: Starting /mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/mdi/mdi...
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
"START TASK DEBUG lambda ... int MainWindow_Bluetooth::setupLambda()89"
index_sub 0
"END TASK DEBUG lambda... int MainWindow_Bluetooth::setupLambda()213"
19:31:54: /mnt/A_BT_DEC10/BT__PROGRAMS/A_JAN11/A_BT_LIBRARY/mdi/mdi exited with code 0
|
|
|
|
|
Best guess? Wrong forum. AFAICT this is a QT issue. QT ≠ C++. While QT does use C++ as a base, it's a framework on top of C++. You are more likely to get an answer either from a QT specific forum, or from the site you got your examples from.
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
So you do not think this is my fault - wrong usage of C++?
"connect " is Qt specific , but lambda is C++ or am I wrong?
I did post same on QT forum and I fully expect somebody to say _ this is C++ code problem "...
But if I continue this discussion here ... I will end up banned......
.,..in that case..
Thanks and have a swell day...
|
|
|
|