|
I am trying to improve my error handling skills.
I am somewhat happy with "perror", but that "requires" that the preceding code can report meaningful error messages. Most of the time all I need is "success" message and nothing more specific when error occurs.
There is a "feature" in Eclipse IDE which let me "surround" selected code , try /catch is one of them.
However, being a greenhorn , I cannot decipher this error message I am getting
Exception does not name a type
I know what "does not name a type" means , but HOW do I fix it for "Exception"?
I did Ask Mrs Google and she did not help much.
The extra block in the code is there because I just "surrounded" the perror line.
Of course the actual error message is not yet there, until I fix this missing type error.
Help will be appreciated.
Cheers
Vaclav
<pre lang="c++">
// returns file descriptor
int memfd = open("/dev/mem", O_RDWR | O_SYNC);
if(memfd)
{
try {
perror("Failed open /dev/mem ");
} catch (Exception e) {
}
exit(1);
}
</pre>
|
|
|
|
|
Before using a feature you should know about it:
Exceptions - C++ Tutorials
Then you should realise that catching exceptions makes only sense when functions called inside the try block might throw them. But C standard library functions like perror() do not throw them (because it is a C++ feature, the C standard does not define them).
Finally you have to know which kind of exceptions (types) might be thrown. Implement a catch block for each of them. With functions from the C++ standard library, these are std::exception - cppreference.com[^] and derived ones.
An example:
#include <exception>
std::ifstream file;
file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
try
{
file.open("test.txt");
file.close();
}
catch (std::exception& e)
{
cout << e.what() << '\n';
}
|
|
|
|
|
You cannot catch something that is not a catchable type. And since perror does not throw anything the above code serves no purpose. You can either create your own throwable type or use the <exception> class[^]
|
|
|
|
|
Thanks guys.
If I may translate what you have said - it is pretty clear that to use exceptions it has to be "defined" and then implemented / enabled in / by the object throwing it. . Hence missing type error I received.
I can see using it in (random) file access, but would it help in writing to hardware I/O via memory map?
I am not sure if such error checking would be an overkill - either the I/O is accessible in its entirety or it is not at all.
If individual address fails it is not coded by me correctly.
Cheers
Vaclav
|
|
|
|
|
This is a complex thing so lets go thru it.
On a Normal O/S, RTOS very few low level functions ever have exception catches they usually simply report it back. The why is simple, the problem it faces is how the exception should report the error, it isn't clear who it should be reported to the APP or the O/S.
As an example, early versions of Windows when low level functions raised an exception put up the blue screen of death and silly things on the API could create it.
Blue Screen of Death - Wikipedia[^]
It actually became a problem because people got sick of rebooting there computer and on the modern versions of windows it is reserved for unrecoverable errors.
Almost all the core windows API almost never raises an exception it simply passes the error back to be handled by the caller because part of being able to handle the error is to know what the caller program is which only the caller knows.
So basically there is no problem something like an APP raising exception it can rely on the O/S being able to do something sensible with the exception. However if the caller is something like a driver or the O/S itself there is always the problem the thing you are reporting to has already crashed. So in your case file I/O may well be used by a driver so no-one would set it up to raise an exception.
Now there are even newer changes in programming to Virtual O/S which started with VMware. There you have a hypervisor program and the O/S or OS's run above the hypervisor
Hypervisor - Wikipedia[^]
In that enviroment many low level functsions will raise an exception and the Hypervisor will catch them because it is immune to errors in the VM. So in that situation a file IO may well be setup to raise an exception.
See the common theme if you are going to raise an exception the thing that catches the exception must be able to continue running despite the error.
So the question of if a low level function should raise an exception depends on there being a stable level below it to catch the raised error.
What this answer brings in is the concept of protection rings the wiki entry is very Intel centric
Protection ring - Wikipedia[^]
You are mainly working on the Pi and on ARM processor they call it EXCEPTION LEVELS and we shorten it to EL. This is the setup on Pi3 which runs Cortexa53 cores it has EL0, EL1, EL2, EL3
CortexA-53 Exception Levels[^]
You will note they describe what parts of a system they expect to be running at what level
EL0 = Applications.
EL1 = OS kernel and associated functions that are typically described as privileged.
EL2 = Hypervisor.
EL3 = Secure monitor.
Now just to put that in perspective when you run your Raspbian linux it only uses EL0 & EL1 there is just a pass thru bootstub for EL2 & EL3 so you could say it doesn't use the CortexA53 to it's full capabilities. The reason why is that there are lots of processors out there that don't have it's protection level abilities and it would require a special version of linux to support it.
Now specifically in your case because you are writing code inside linux, your file i/o will be EL1 but your app will be EL0 ... there is a complex issue ... you are trying to make EL0 handle EL1 errors and it doesn't have the permissions to do so. It requires a very complex setup with callbacks that I won't go into unless you want.
Hopefully you see the answer to your question gets incredibly complex.
In vino veritas
|
|
|
|
|
below is an hackerrank question link where i am encountering an segmentation falut.
HackerRank[^]
and this is my solution
#include <iostream>
#include <vector>
using namespace std;
void fillVector(vector<int> &temp, unsigned long number);
void RotateVector(vector<int> &arr1, vector<int> &arr2, unsigned long k);
int main(){
unsigned long n,k,q;
cin >> n >> k >> q;
vector<int> a, b;
fillVector(a, n);
fillVector(b, q);
RotateVector(a, b, k);
return 0;
}
void RotateVector(vector<int> &arr1, vector<int> &arr2, unsigned long k){
unsigned long arraySize = arr1.size();
unsigned long querySize = arr2.size();
unsigned long rotation = k, i;
unsigned long start = rotation%arraySize;
if(rotation<arraySize) start=rotation;
vector<int> rotatedArray;
for(i=0; i<arraySize; i++){
if(((arraySize-rotation)+i) < arraySize){
rotatedArray.push_back(arr1[(arraySize-rotation)+i]);
}
else{
rotatedArray.push_back(arr1[i-rotation]);
}
}
for(i=0; i<querySize; i++){
cout << rotatedArray[arr2[i]] << endl;
}
}
void fillVector(vector<int> &arr, unsigned long n){
unsigned long temp;
for(int i=0; i<n; i++){
cin >> temp;
arr.push_back(temp);
}
}
the above solution is giving segmentation fault and i am not able to detect it.(rest all the test-cases are passed)
here are the links to that test case inputs : https://hr-testcases-us-east-1.s3.amazonaws.com/1884/input04.txt?AWSAccessKeyId=AKIAJ4WZFDFQTZRGO3QA&Expires=1527377038&Signature=sA5C43bnnqyLeXwWA9L16en3rEE%3D&response-content-type=text%2Fplain
and expected outputs : https://hr-testcases-us-east-1.s3.amazonaws.com/1884/output04.txt?AWSAccessKeyId=AKIAJ4WZFDFQTZRGO3QA&Expires=1527377042&Signature=%2BSyDUj0B5DwySkSPGjiwfmB7MlE%3D&response-content-type=text%2Fplain
Edit :
Below is the working code:
#include <bits/stdc++.h>
using namespace std;
void fillVector(vector<int> &temp, unsigned long number);
void RotateVector(vector<int> &arr1, vector<int> &arr2, unsigned long k);
int main(){
unsigned long n,k,q;
cin >> n >> k >> q;
vector<int> a, b;
fillVector(a, n);
fillVector(b, q);
RotateVector(a, b, k);
return 0;
}
void RotateVector(vector<int> &arr1, vector<int> &arr2, unsigned long k){
unsigned long arraySize = arr1.size();
unsigned long querySize = arr2.size();
unsigned long rotation = k, i;
unsigned long start = rotation%arraySize;
if(rotation<arraySize) start=rotation;
vector<int> rotatedArray;
for(i=0; i<arraySize; i++){
if(((arraySize-start)+i) < arraySize){
rotatedArray.push_back(arr1[(arraySize-start)+i]);
}
else{
rotatedArray.push_back(arr1[i-start]);
}
}
for(i=0; i<querySize; i++){
cout << rotatedArray[arr2[i]] << endl;
}
}
void fillVector(vector<int> &arr, unsigned long n){
unsigned long temp;
for(int i=0; i<n; i++){
cin >> temp;
arr.push_back(temp);
}
}
Thank you.
modified 6-Jun-18 1:05am.
|
|
|
|
|
You need to step through your code with the debugger to find out where the segv occurs.
|
|
|
|
|
You correctly define start Quote: unsigned long start = rotation%arraySize; and then miss the opportunity of using it.
By the way, in my opinion, you don't even need to actually rotate the vector.
modified 29-May-18 7:44am.
|
|
|
|
|
|
Hi,
I am new to graphical representation of Data.I have some data like speed ,altitude etc raw file.These parameters i have to represent in graphic.Which programming language is better .Web interface is not required.
|
|
|
|
|
sree79 wrote: Which programming language is better Whichever one you are most skilled at. Moxt languages have built-in, or third-party, libraries for such applications. Google will probably find you more information.
|
|
|
|
|
You can just throw the raw data in a spreadsheet and they have graphing abilities.
The first question you need to ask yourself is do you really need to program anything?
In vino veritas
|
|
|
|
|
|
<b>I am reposting this in an attempt to focus on the issue.
THIS IS NOT A BUMP! ( I know better ) </b>
I am well aware what volatile keyword does.
In my application it prevents accidental access to memory AKA RPi hardware.
The task is to map the hardware to memory. It works just fine resulting in "base" pointer to memory map.
Now I need to add specific offset to the "base" and have the "result" to be of volatile type.
The included snippet of test code does that with ONE exception - no matter what combination of code I use I cannot achieve VALID <b>volatile</b> result.
It only works when no volatile keyword is used , none at all.
I did try casts and dynamic_cast.
I have optimizer turned off and obviously doing something wrong applying pointers.
This code test snippet is located in main(), no other code is involved.
It gives pointer to "base" ( value is irrelevant) and adds "int" offset and produces new "result" pointer.
<pre lang="c++">
int *base;
int offset = 1;
int *result;
result = base + offset;
</pre>
Any help will be greatly appreciated.
Cheers
Vaclav
|
|
|
|
|
You have not declared result as volatile, and it is not clear what you are actually trying to achieve. How do you determine that the variable is not volatile?
|
|
|
|
|
Indeed.
|
|
|
|
|
It's all cleared up .. ostream has a behaviour with volatile pointers
Quote: There are no overload for pointers to non-static member, pointers to volatile, or function pointers (other than the ones with signatures accepted by the (10-12) overloads). Attempting to output such objects invokes implicit conversion to bool, and, for any non-null pointer value, the value 1 is printed
It prints 1 because the volatile pointer he makes is non zero and that is what the ostream standard says it should do.
I must admit I hadn't run across it because I rarely use the ostream to output because of quirks like this.
In vino veritas
|
|
|
|
|
|
Richard is right; what you expect as a 'valid volatile result'? How do you check it?
|
|
|
|
|
<pre lang="c++">
cout << "base " << base << '\n';
cout << "offset " << offset << '\n';
cout << "result " << result << '\n';
</pre>
Please read the OP again.
Here is a repeat.
Base gets set to a pointer, simple , right?
I add an "offset" to it, still pretty straight.
I expect the result pointer to be base plus offset.
It is <b>AS LONG AS NONE</b> of the variables is typed with "volatile" keyword.
|
|
|
|
|
Your current code as posted will print some random value because you haven't set the variable base to a start value.
Specifically it will be what junk is the memory address it gets assigned, basic rules of C.
Could you please try this code
#include <stdio.h>
int main (void){
int *base = 0;
int offset = 1;
volatile int *result;
result = base + offset;
printf("Volatile result pointer = %p\n", result);
if ((int)result != sizeof(int)) printf("compiler is broken\n");
}
It should return 2, 4 or 8 for the result depending on the size of int on your compiler
As you are doing pointer addition the offset is defined as the sizeof(int) by C standards.
If you see the message "compiler is broken" there are 10 different gcc compilers for the Pi use another one or change version of your current.
GCC being a public domain support compiler does get bugs in versions from time to time.
As a last comment the above possible multiple answers is specifically why you shouldn't use int for hardware registers.
The registers on the Pi have to be accessed as 32bit, so the only safe way to do it is uint32_t
The following code will give an answer of 4 on EVERY C COMPILER, it is safe and portable and even works on the Pi3 64bit compilers
My advice is DO IT THIS WAY.
#include <stdint.h>
#include <stdio.h>
int main (void){
uint32_t *base = 0;
uint32_t offset = 1;
volatile uint32_t *result;
result = base + offset;
printf("Volatile result pointer = %p\n", result);
}
In vino veritas
modified 22-May-18 22:32pm.
|
|
|
|
|
OK, it's late but here is the latest.
This code with result declared as volatile PRINTS the correct value of "result".
However "cout" outputs value of 1 - that is ONE.
After removing "volatile" from declaration of result - cout will output 4.
I'll let you gentlemen decide where is my problem , it the meantime I am initializing the pointer to zero and will be checking for absence of zero and hoping computer is adding the values correctly.
BTW the correct additions of both values was never my concern , hence I did not care about the uninitialized value of "base" and was using "int" to test.
.
<pre lang="c++">/*
uint32_t *base = 0;
uint32_t offset = 1;
volatile uint32_t *result;
result = base + offset;
printf("Volatile result pointer = %p\n", result);
*/
uint32_t *base = 0;
uint32_t offset = 1;
volatile uint32_t *result;
result = base + offset;
cout << "base " << base << '\n';
cout << "offset " << offset << '\n';
THIS LINE IS AN UNRESOLVED ISSUE
OUTPUT IS CORRECT WHEN NO VOLATILE KEYWORD IS USED
result = 1 WHEN VOLATILE IS USED
cout << "result " << result << '\n';
this always prints correct value
printf("Volatile result pointer = %p\n", result);
</pre>
PS
ill try "bad compiler" in the morning.
|
|
|
|
|
That ostream object is a pile of overloaded functions on the operator <<
std::basic_ostream::operator<< - cppreference.com[^]
NOTE FROM ABOVE .. I underlined the statement parts:
Quote: There are no overload for pointers to non-static member, pointers to volatile, or function pointers (other than the ones with signatures accepted by the (10-12) overloads). Attempting to output such objects invokes implicit conversion to bool, and, for any non-null pointer value, the value 1 is printed
I avoid the thing like the plague because you have to know it's behaviour .. so yes a non zero volatile pointer will always print as 1 .. it tells you that.
So the good news is there is nothing wrong with your compiler it is following the c++ standard.
If you don't like it take it up with the c++ standard comittee.
Ostream has other strange (but documented) filter behaviour.
For example with char* pointers it has a special overload expecting it to be a pointer to a null terminated string
cout << (char*)0x41 << endl;
cout << (void*)0x41 << endl;
You could try putting a void* typecast so it goes thru the void* pointer overload ... like so should work
cout << "result " << (void*)result << '\n';
If you are intending to use ostream you will need to learn it's ins and outs and quirky behaviour.
Anyhow it's not a big issue and rolls around ostream behaviour .. so don't make it more than what it is.
Your pointers are clearly adding properly you were just having a display issue with ostream
In vino veritas
modified 23-May-18 1:08am.
|
|
|
|
|
Leon and everybody, thanks for all your help.
Now I can sleep better.
One more "thing" - if I use uint32_t adding 1 results in pointer being incremented by 4. If I use uint8_t same process increments the pointer by 1.
So - is the BCM2835 memory "only" 8 bits wide?
Cheers and thanks again.
Vaclav
Somebody is trying to tell me something - I just got very close hit by lightning and lost power so I have to start over.
This "byte" reference make no sense to me.
If uint32 is 4 bytes wide - why did they name it "32"?
uint32 IS 32 bits variable and if adding 1 uint32 variable to the original pointer comes up with ADDRESS offset of 4 that means there are 4 8 bits wide memory locations AKA memory is 8 bits wide.
I know I am not the best communicator - but I never did question pointer arithmetic.
I do not get why some people always volunteer to "teach" and then complain about it.
Ever since I join this forum I appreciated straight talk, now it looks very similar to forum ,which should remain nameless, - everybody is a teacher and fails to read the posts.
Of course when I express my feelings I get flamed.
I better quit - the storm is getting too close.
-- modified 23-May-18 12:54pm.
|
|
|
|
|
Quote: So - is the BCM2835 memory "only" 8 bits wide?
What do you mean with that?
|
|
|
|
|