What can be inputted in the following program to access the array? - c++

Since x is not really validated and is received through scanf, there should be potentially tainted data that can be used to access bytes.
Code (not really logically doing anything productive):
void getMyBytes(){
int x, byte;
int bytes[20];
scanf("%u %u", &x, &byte);
bytes[x-1] = byte;
}
A known simple (ugly) fix for this code is:
void getMyBytes(){
int x, byte;
int bytes[20];
scanf("%u %u", &x, &byte);
if (x > sizeof(bytes)/sizeof(*bytes)) return; --> validation fix
bytes[x-1] = byte;
}
What inputs can I enter in scanf so that I can access bytes?

This depends on your application but you should always bound check external input when accessing your internal members. How you report this is up to you. But consider using the std::vector or std::array to help you out. In your example:
void getMyBytes(){
int x, byte;
std::array<int, 20> bytes; // Bad name btw, an int is very unlikely to be a byte.
scanf("%u %u", &x, &byte); // scanf is not type safe. Consider using cin <<
bytes.at(x-1) = byte; // Automatically bound checks for you and will throw an exception
// in the case that you are out of bounds. Very useful :)
}
std::array::at:
Returns a reference to the element at specified location pos, with bounds checking.
If pos is not within the range of the container, an exception of type std::out_of_range is thrown.
Other ways you might report the error include:
Hard death in debug: assert(x >= 0 && x < bytes.size() && "I crashed here because you gave me bad input!")
Error reported to function caller: if (x < 0 || x > bytes.size()) { return false; }
Throw with more info: if (x < 0) { throw my_special_underrun_exception; } and if (x > bytes.size()) { throw my_special_overrun_exception; }
Finally consider visiting the CppCoreGuidelines for plenty of tips about how to write good code.

Related

Handling an error condition in the compare function of std::qsort

I am trying to figure out a way for qsort to throw an exception or indicate an error condition if the compare function finds that the elements are, for some reason, invalid for sorting.
For example, in this compare function, I need to indicate an error condition that my sorting is invalid if the return value of some_function is 5.
How should I modify my compare function?
int compare (const void * a, const void * b)
{
int ret1 = some_func(a);
int ret2 = some_func(b):
return ( ret1 - ret2 );
}
I am dealing with a legacy code base so I'm not in the position to use std::sort and due to the nature of the implementation calling some_func before hand might also involve huge amount of changes so I'm looking to understand if a workaround is possible.
C++ allows you to throw whatever you need, not only exceptions but also other types, you could do something like throw an int if it suits your purposes and catch where you call the function with a try-catch block.
For what you need I think you can use STL exception library:
Demostrative example:
#include <iostream>
#include <exception>
int count = 0;
int compare(const void *a, const void *b)
{
int ret1 = *(int*)a > *(int*)b;
if (++count == 5) //throws exception when count reaches 5
throw std::invalid_argument("Argument is not sortable");
//you could throw count by simply using throw count
return ret1;
}
int main()
{
int x[]{2,1,3,5,6,1,7,2,5,3};
try
{
//will sort until exception is thrown
qsort(x, sizeof x / sizeof *x, sizeof(int), compare);
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl; //print exception in the console
//handle the exception here
//if you were to throw count you could cach it with
//catch (int &e)
}
//note that the values were sorted until the exception was thrown
for (int i = 0; i < sizeof x / sizeof *x; i++){
std::cout << x[i] << " ";
}
}
Output:
Argument is not sortable
1 2 3 5 6 1 7 2 5 3
^
sorting
stopped
here
Throwing an exception is potentially expensive, so you probably want to return an error condition. However, doing either approach inside the compare function is needlessly expensive in this case, since you would be doing the check multiple times for every element. Instead, you could just check for the error condition before calling qsort which is much more efficient:
auto ok = std::none_of(/* range */, /* predicate */);
if (ok)
std::qsort(/* ... */)
else
// report error

method giving app crashes due to segmentation fault in c++

this simple loop method is unable to run and an error arises "app crashed". when i checked this in an online compiler it gave 'segmentation fault(core dumped)'-
string studies(setMatter ch) {
string a = "LISTEN CAREFULLY!\n";
int i = 0;
while (i <= ch.a.quantity()) {
a += ch.a.getAns(i);
i++;
}
return a;
}
also see for reference of methods in the above code-
class Answer {
private:
vector<string> ch;
public:
void setAns(string ans) { ch.push_back(ans); }
string getAns(int num) { return (ch[num]); }
int quantity() { return ch.size(); }
};
am i accessing elements out of bond? but i dont know where as i every number starts from 0 in programming
Yes you are.
while(i<=ch.a.quantity()){
should be
while(i<ch.a.quantity()){
Valid vector indexes are zero up to the size of the vector minus one. That should be obvious, if the valid indexes started at zero and went to the size of the vector then there would be one more valid index than the size of the vector, which makes no sense.
Generally you use a for loop for this kind of task
for (int i = 0; i < ch.a.quantity(); i++) {
a += ch.a.getAns(i);
}
It's a little easier to read that way.

Handling int and std::vector::size_type in comparsion

So I have something like this (C++03):
class MyClass
{
// ...
}
class something
{
private:
std::vector<MyClass*> container;
// ...
}
// cmdarg can be anything, negative int too...
void something::foo(const std::string& cmdarg)
{
const int res = std::stoi(cmdarg);
if (res >= 0 && static_cast<std::vector<MyClass*>::size_type>(res) < this->container.size())
{
// ...
}
}
I would like to ask if the conversion from int to std::vector<MyClass*>::size_type is valid. The res >= 0 says it's non negative, so I guess converting to an another non-negative number is okey.
My problem is, if I write
if (res >= 0 && res < container.size())
I get a warning, because of comparsion with signed and unsigned integer types.
My above code (the full one) compiles and seems to work, but I'm not sure.
Thank you.
Your code looks a bit too perfect for my taste.
Breaking it down:
const int res = std::stoi(cmdarg);
if (res >= 0 && static_cast<std::vector<MyClass*>::size_type>(res) < this->container.size())
The if-statement for checking below zero is nice. Personally I would write this as:
if (res < 0)
{
std::cerr << "Negative number " << res <<" given for ..., a positive was expected" << std::endl;
return -1;
}
This leads us to the cast:
auto unsigned_res = static_cast<std::vector<MyClass*>::size_type>(res);
However, size_type this vector always size_t as it uses the std::allocator. In code review, I would request to change this for readability to:
auto unsigned_res = static_cast<std::size_t>(res);
Finally, you can indeed nicely compare it:
if (unsiged_res < container.size())
// Do something
Note that I mentioned both the comparison and the cast, as this needs to happen in that order. On top of that, you also need some exception handling for when std::stoi fails, see it's documentation
For more details on how to correctly deal with signed/unsigned, I can recommend this article on ithare.

Prevent a returning function from execution if a condition on parameters is true

like said on the title, I was wondering if it was possible to stop a function from execution. In my particular case, I'm trying to make an operator[] and prevent utilisator from using it if the value gave in parameters is too high :
in .h:
class Vec4
{
float x,y,z,w;
public:
float operator[](const unsigned int i);
}
in .cpp :
float Vec4::operator[](const unsigned int i)
{
if(i == 0) return x;
if(i == 1) return y;
if(i == 2) return z;
if(i == 3) return w;
}
I'd like to "break" the function if i >=4
For the moment I'm just making a console output and return 0.0f
thank you to show me if there is a way ... or not !
You can do at least 4 things.
Return a known error value from the function. For eg. -1 if the input value is no good.
Raise an exception.
Change the function to pass output by reference and return an error code.
Force the user to get the point with a strongly typed enum class.
Option 1
float Vec4::operator[](const unsigned int i) {
switch (i)
case 0:
return x;
...
default:
return nan;
Option 2
default:
throw InvalidInputException;
Option 3
typedef ErrCode int;
const int ERROR = -1;
const int SUCCESS = 1;
...
ErrCode Vec4::getPoint(const unsigned int i, float &ouptut) {
...
switch (i)
case 0:
output = x;
return SUCCESS;
default:
return ERROR;
Option 4 (c++11)
class Vec4 {
...
public:
enum class VecMem {X, Y, Z, W};
float Vec4::getPoint(VecMem member) {
switch (member):
case X:
return x;
...
Usage:
Vec4.getPoint(Vec4::VecMem::X);
Use "switch case " and for the case where value is différent bigger than 3 return a default state which can be a specific value reserved for this case
If your argument is known during the compilation, you can use a static_assert.
#include <cassert>;
constexpr float Vec4::operator[](const unsigned int i)
{
static_assert(i <= 3);
...
}
Static assertions are not impacting performance as they are checked during the compilation.
If your argument isn't known during the compilation, you can use dynamic assert.
#include <cassert>;
float Vec4::operator[](const unsigned int i)
{
assert(i <= 3);
...
}
Dynamic assertions are contained in compiler output only after setting compiler flags that enable them, so can be switched off easily.
Or you can just throw an exception.
float Vec4::operator[](const unsigned int i)
{
if (i > 3)
{
throw BadArgumentException("i must be <= 3");
}
...
}
Exceptions can contain a lot of information and be handled in other parts of the code, but have the biggest performance cost.
http://en.cppreference.com/w/cpp/error/assert
If you don't mind using upcoming features, you can use std::optional to do that:
std::optional<float> Vec4::operator[](const unsigned int i) {
if(i == 0) return x;
if(i == 1) return y;
if(i == 2) return z;
if(i == 3) return w;
return {};
}
The drawback is that the caller must check the validity of the returned value (using either the operator bool or the has_value member function) or use the value_or member function to get a default value for empty optionals.

Taking in array of unknown size in c++

Ok I am extremely new to programming, and I am taking a c++ class. Basically for the current project I have to take in an array of unknown size, resize it, and output a bunch of statistics like average, Q1, Q3, etc. I am having trouble taking in the array from the user. I need to quit taking in variables once they enter 0. Here is what I have:
int i = 1; //When I first posted this I didn't mean to comment out the '= 1' part
do {
cin >> array[i];
if (array[i] != 0)
return true;
} while (true);
What am I doing wrong? the program stops after I enter 1 number every time no matter what number I enter.
I am using vector class btw.
Do the following:
// change int to your type
int val;
std::vector<int> vec;
while(std::cin >> val) {
if(val == 0) break;
vec.push_back(val);
}
Reason: Stating a return clause causes to exit the loop.
use of std::vector ensures the arbitrary size condition.
Update after #nonsensickle's constructive remark:
The following piece of code also ensures the only 0 terminates input process condition:
// change int to your type
int val;
std::vector<int> vec;
do {
if(std::cin >> val) {
if(val == 0) break;
vec.push_back(val);
} else { // fix broken input stream in case of bad input
std::cin.clear();
std::cin.ignore(1,'\n');
}
} while(true);
and a more sophisticated way, although overkill but what the hell :), with templates and type traits:
template <typename T>
struct zero_traits
{
static T getzero() { return T(0); }
};
template <>
struct zero_traits<std::string>
{
static std::string getzero() { return "0"; }
};
template <>
struct zero_traits<char>
{
static char getzero() { return '0'; }
};
template <typename T>
std::vector<T> read_values()
{
T val;
std::vector<T> vec;
do {
if(std::cin >> val) {
if(val == zero_traits<T>::getzero()) break;
vec.push_back(val);
} else {
std::cin.clear();
std::cin.ignore(1,'\n');
}
} while(true);
return vec;
}
int main()
{
// change int to your type
std::vector<int> vec = read_values<int>();
for(auto i : vec) std::cout << i << std::endl;
}
First of all i will never increment.
Second of all, if (array[i] != 0) will return if that array's value doesn't equal 0.
You need to read into how do { ... } while() loops work as well as what return statements do. Might as well throw in how to increment an array while you're at it.
I will not try to answer your question directly. What you have is a small logic error and a misunderstanding of the do {...} while () looping construct. What you need is to learn how to step through your code.
Let's go through your code line by line (there are only 6 lines here so it should be really easy):
int i; - Ok, so we are declaring an integer i here but are not giving it a value. As such, i can have a random value.
do { - This is where we will come back to when we evaluate the while clause. But only if the result of the while clause is true.
cin >> array[i] - Store a value that the user enters in the array at the position i. Here we ask ourselves a question, what is i? We should know its value without having to run the program. Hint: there's a problem here because of i
if (array[i] != 0) - If the number entered by the user is not zero return true (exit this function with the result true).
} while (true); - Go back to the do { line and redo all the steps until you get here. There is no condition here so it will keep happening until we exit this function.
Hint: The only exit point of your loop is at step 4.
With this, you should be able to figure out your problem. Trying to break down the problem for yourself should be your first step.
I recommend reading this blog post on debugging small programs. It should be informative.
Though code posted by others (in particular #DimitriosBouzas) will work, and is the better choice, I strongly recommend fixing your code and learning why it failed. This will help you in the long run more than #DimitriosBouzas' elegant solution.
Before answering your question.
Initialize your variables int i=0; .You assign i to be zero because arrays are zero indexed.
You have to incerement i. If do not increment it, i will point at the first "bucket" in your array the whole time. Use i++ or i = i + 1 after every iteration of the do while loop to move "forward" in your array.
You want your program to run until zero is entered so you have to write your condition like this if (array[i] == 0) return true;. This condition is true when the last number entered was zero and it will cause your method to return. It would be more elegant for you to check for it in the while clause.
Putting it all together, your code should look like this
int i=0;
do {
cin >> array[i];
if (array[i] != 0) break;
i++;
} while (i < maxSize);
//do stuff with filled array