|
To me that was always the 'fun' part of C++ versus Java and C# - figuring out exactly what was being thrown in the first place.
|
|
|
|
|
In Windows, there are additional, O/S-level exceptions, that provide this sort of information. Look for "Structured Exception Handling". If you use MSVC, you may use the _set_se_handler function in main() and in the main function of each thread to convert Structured Exceptions to C++ exceptions.
There may be similar O/S- and compiler-specific methods in other environments.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
I have the following file code:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
string path = "student/text/readpractice.txt";
try {
ifstream file;
file.open(path); if (!file) {
throw runtime_error("File failed to open.");
}
cout << file.rdbuf(); file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
return 0;
}
Can someone help me understand how this line works:
if (!file) {
How can you use the exclamation point operator on what is probably a class?
Is there some type of overloading that has occurred? I looked thru the code, and I couldn't find the ! point being overloaded.
Any ideas?
Thanks.
|
|
|
|
|
|
Interesting.
I tried doing a "Step Into" on that line in the debugger, but it won't go to it.
If I do a "Go to Definition", it goes to this in xiosbase:
_NODISCARD bool __CLR_OR_THIS_CALL operator!() const noexcept {
return fail();
}
However, I put a breakpoint there, and it doesn't break.
|
|
|
|
|
I wrote the following code to output the Greek word "Δέλτα":
#include <iostream>
#include <io.h>
#include <fcntl.h>
using namespace std;
int main() {
_setmode(_fileno(stdout), _O_U16TEXT);
cout << "\u0394\u03AD\u03BB\u03C4\u03B1" << endl;
return 0;
}
For some reason, I get this error:
---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Debug Assertion Failed!
Program: ...sers\Owner\source\repos\assert_test\x64\Debug\assert_test.exe
File: minkernel\crts\ucrt\src\appcrt\lowio\write.cpp
Line: 659
Expression: buffer_size % 2 == 0
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
---------------------------
Abort Retry Ignore
---------------------------
Any ideas why the code is producing that error?
Thank you.
|
|
|
|
|
First things first, you're ignoring the return value of _setmode. If it's -1, the call failed, but you'll never know.
Second, after reading the documentation on _setmode and associated error links, it appears you cannot use cout with the mode of stdout switched to Unicode. You have to use wprintf instead:
#include <iostream>
#include <io.h>
#include <fcntl.h>
using namespace std;
int main()
{
int r;
r =_setmode(_fileno(stdout), _O_U16TEXT);
if (r == -1)
perror("Cannot set mode");
wprintf(L"\u0394\u03AD\u03BB\u03C4\u03B1\n");
return 0;
}
CORRECTION: You CAN use COUT, but you must use the wide version of it, but note the L in front of the string being output. It MUST be there:
#include <iostream>
#include <io.h>
#include <fcntl.h>
using namespace std;
int main()
{
int r;
r =_setmode(_fileno(stdout), _O_U16TEXT);
if (r == -1)
perror("Cannot set mode");
wcout << L"\u0394\u03AD\u03BB\u03C4\u03B1" << endl;
return 0;
}
|
|
|
|
|
I wrote this code:
class ChessPiece
{
};
int main()
{
cout << "size:" << sizeof(ChessPiece) << endl;
}
For some reason, it prints out 1 instead of 0. Anyone know why?
Thanks.
|
|
|
|
|
Probably because there has to be some minimum size of a class. You could study the C++ standard to see why.
|
|
|
|
|
Perhaps take a look at this FAQ.
Stroustrup: C++ Style and Technique FAQ[^]
"the debugger doesn't tell me anything because this code compiles just fine" - random QA comment
"Facebook is where you tell lies to your friends. Twitter is where you tell the truth to strangers." - chriselst
"I don't drink any more... then again, I don't drink any less." - Mike Mullikins uncle
|
|
|
|
|
That is interesting.
That page references a 'better' link. Same answer is there.
Standard C++[^]
Myself though if Stroustrop is the name then I would consider that better.
modified 2-Jan-24 12:43pm.
|
|
|
|
|
jschell wrote: if Stroustrop is the name then I would consider that better. Agreed.
"the debugger doesn't tell me anything because this code compiles just fine" - random QA comment
"Facebook is where you tell lies to your friends. Twitter is where you tell the truth to strangers." - chriselst
"I don't drink any more... then again, I don't drink any less." - Mike Mullikins uncle
|
|
|
|
|
Voluntarily removed - incorrect forum.
modified 1-Jan-24 23:53pm.
|
|
|
|
|
The << in this is not shift left, it is operator<<() operating on whatever QStringList() returns. It might be concatenating them, or appending them to an array, or whatever.
It can handle both char* and QString because it probably has overloads for both types, or possibly because QString has an operator for returning a char* .
I'm guessing this from the context because the C++ standard library also uses << this way - you would have to consult the QT documentation to be sure.
|
|
|
|
|
Thank you.
Appreciate your help.
Am I understanding it correctly - "<<" is pretty much like passing a parameter to a function ?
I am still not clear about "where -c " is passed to - is it an option to QStringList or "/bin/sh"?
I believe it is "passed to QStringList" since that is a second parameter to QProcess.
Perhaps now I can make more sense from QT docs, both - QProcess and QStringList.
I also need to look at the source of "sh"...
|
|
|
|
|
I'm in agreement with Richard on what is actually happening there. It looks like the QStringList is being used to join all the arguments together to make a complete command line for passing to the QProcess .
/bin/sh is the Bourne shell, you should be able to find the manual page for it online or by typing "man sh" in your Linux terminal. I don't know why it is using a shell instead of executing the command directly, but I suspect there is a good reason. Maybe for wildcard parsing or terminal I/O buffering.
|
|
|
|
|
Message Closed
modified 2-Jan-24 12:45pm.
|
|
|
|
|
xterm will only return whether xterm itself failed or not. So for example xterm -e /bin/false returns true (0), since xterm executed successfully.
I'm suspicious about your approach, here though. Can you not run your command directly via QProcess, rather than launching an xterm? I am assuming 2 things here: 1) you need to capture the output of command , at least in part, and 2) QProcess can do that for you, similar to using pipe() , rather than using system() to run a shell command from a program.
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
k5054 wrote: I'm suspicious about your approach
I agree with that.
|
|
|
|
|
Message Closed
modified 2-Jan-24 12:45pm.
|
|
|
|
|
You can tell sudo to allow certain users the ability to run a given command without having to prompt for a password. For example you might add a file foo to the /etc/sudoers.d directory
# allow user "joe" to use command /usr/sbin/foobar
joe ALL(ALL) NOPASSWD:/usr/sbin/foobar
# allow users in group foo to use command /usr/sbin/frobnicate
%foo ALL(ALL) NOPASSWD:/usr/sbin/frobnicate
Google for sudoers to see what other options you have for the sudoers file.
But you should be aware that any time a user process "needs" sudo access, its something of a smell. That is it should be considered a signal that there may be something fundamentally wrong with the approach to solving the problem. If your app definitely, absolutely, no-question-about-it needs to elevate its permissions to perform some tasks, I would be inclined to write a program that only does that one thing, and use setuid/setgid with appropriate setuid/setgid permissions e.g.
$ ls /usr/local/bin/foo
---s--x--x 1 root root 12345 Jan 1 08:00 /usr/local/bin/foo
and the code for foo would do something like
std::string build_cmd_str(int argc, char argv)
{
std::string cmd{"/usr/local/bin/foo"};
/ build up rest of command string here */
if(bad_things_happened) {
cmd.erase();
}
return cmd;
}
main(int argc, char *argv[])
{
std::string cmd{build_cmd_str(argc, argv)};
if(cmd.length() == 0) {
return -1;
} else {
setuid(0); FILE *p = pipe(cmd.c_str(), "r");
pclose(p);
}
return 0;
}
This can be as simple or complex as you need, but should only execute one system command. Ideally, if you only need to run something as perhaps the database administrator, the helper program would have setuid as the dba, not root.
"A little song, a little dance, a little seltzer down your pants"
Chuckles the clown
|
|
|
|
|
k5054 wrote: I would be inclined to write a program that only does that one thing, and use setuid/setgid with appropriate setuid/setgid permissions e.g.
That sounds like a really good solution to me.
|
|
|
|
|
Salvatore Terress wrote: Maybe I need to go back to QT forum to resolve this Definitely yes, as none of this has anything to do with C++. I have looked at the documentationm for QStringList and QProcess , and what you are doing looks correct. But why it fails is impossible to guess.
|
|
|
|
|
Salvatore Terress wrote: I am still stuck at resolving the passing of parameters.
Following is not specific to sudo.
When you execute an OS command in any application the following applies
1. The command to run the executable
2. What happens AFTER the executable starts running.
The first represents the command (binary exe) and the command line options that the command accepts.
What happens with the second depends on the command. But a normal command (non-UI) will be using STDIO (stdin, stdout, stderr.)
The second can NOT be controlled with 'parameters'. Only the first can. The only way you can interact with the second in an application is by accessing the STDIO of the application as it runs.
The second becomes more complicated if the application has a GUI. It can also be more complicated in specific situations depending on exactly what the application does. (There is a way to bypass STDIO.)
For sudo and the first and the way you are executing it with "QP->start" you can only do what the command line options for the command allow. I suspect sudo probably varies by the specific OS. But following is one example.
sudo(8) - Linux manual page[^]
There is no way to change that. Either it is allowed by that or it isn't.
Additionally "start" might have a specific meaning on Windows which can also impact what happens. That doesn't mean is actually applies in this case.
start | Microsoft Learn[^]
|
|
|
|
|
The << operator is an overloaded operator used in C++ stream IO. In basic terms it takes whatever object or value is on the right hand side of the operator, converts it to a string (aka char* ) and sends that to the stream object on the left hand side. So using the standard ouptut stream (console), you can do:
int number = 23;
double half = 23 / 2;
std::cout << "value = " << number << " halved = " << half;
So assuming the items in your code are:
char* command = " hcitool ";
QString string = " dev ";
the result of:
QP->start("/bin/sh", QStringList() << "-c" << command << "-c" << string );
should be:
"/bin/sh -c hcitool -c dev"
sent to the process handler.
Maybe you should spend some more time studying C++, as well as QT.
|
|
|
|