sometimes getting a segmentation fault (core dumped) - c++

my program will sometimes run okay but sometimes it crashes in the middle of running with a segmentation fault. and the fault will come at different times each time i run the program. i debugged with gdb and found that the problem is in this function
int chooseLink(int &h, vector<Edge> &link) {
double r = 1.0*rand() / RAND_MAX;
if (link[link[h].l_ID].q == link[link[h].r_ID].q) { // this is where the error occurs
if (r<0.5)
return link[h].l_ID;
return link[h].r_ID;
}
else {
if (r < link[link[h].l_ID].q / (link[link[h].l_ID].q + link[link[h].r_ID].q))
return link[h].l_ID;
return link[h].r_ID;
}
}
my program involves calling this function millions of times. can anyone suggest what the problem may be? I'm pretty sure the vector 'link' is not going beyond its capacity. this is my first time posting a problem, so sorry if I haven't provided enough information
update
someone asked why i'm passing h by reference. i thought that passing by reference is better than passing by value because it saves space and the program will run faster. is that not correct?
someone asked for the edge class, so here it is
class Edge {
public:
int ID; // ID of edge
bool type; // true for constant, false for variable
double q; // quantity on the edge
int l_ID = 0; // ID of left edge (equals 0 if doesn't exist)
int r_ID = 0; // ID of right edge
void assignType(double &p) {
if (p == 0.5)
type = false;
else
type = true;
}
};
i added a try-catch block to the function so it looks like this:
int chooseLink(int &h, vector<Edge> &link) {
try {
if (h<0 || h>=link.size() ) {
throw h;
}
} catch(...) {
cout << "ERROR: h = " << h << endl;
}
double r = 1.0*rand() / RAND_MAX;
if (link[link[h].l_ID].q == link[link[h].r_ID].q) { // this is where the error occurs
if (r<0.5)
return link[h].l_ID;
return link[h].r_ID;
}
else {
if (r < link[link[h].l_ID].q / (link[link[h].l_ID].q + link[link[h].r_ID].q))
return link[h].l_ID;
return link[h].r_ID;
}
}
and now i don't get the segmentation fault at all. Also, the program runs fine without ever throwing an exception. what's going on? when i remove this try-catch block, i get the segfault again. i don't understand it

The first suggestion is always to boundary or range check your parameters:
int chooseLink(int h, vector<Edge> &link)
{
const unsigned int container_size = link.size();
// Check index for range.
if ((h < 0) || (h >= container.size)
{
// Report error here.
}
else
{
// More checking.
const int left_id = link[h].l_ID;
const int right_id = link[h].r_ID;
if ((left_id < 0) || (left_id >= container.size))
{
// Perform error handling
}
if ((right_id < 0) || (right_id >= container_size))
{
// Perform error handling
}
// remember to use 'const' for items that won't change.
const double r = 1.0*rand() / RAND_MAX;
if (link[left_id].q == link[right_id].q)
{
// ALWAYS use braces, even for single statements.
if (r<0.5)
{
return left_id;
}
return right_id;
}
else
{
if (r < link[left_id].q / (link[left_id].q + link[right_id].q))
{
return left_id;
}
return right_id;
}
// What does it return here?
}
}
When in doubt, range check your variables.
Also, check your logic so that all paths of execution return a value.

Related

Binary Search Recursion warning

#include <iostream>
using namespace std;
int i = 0;
int binarySearch(int arr[],int left, int right, int item)
{
int midpoint;
bool found{false};
if(left < right && !found)
{
midpoint = left + (right - left)/2;
if(arr[midpoint]<item)
{
binarySearch(arr,midpoint+1,right,item);
}
else if(arr[midpoint]>item)
{
binarySearch(arr,left,midpoint-1,item);
}
else
{
found = true;
return midpoint;
}
}
}
int main()
{
int arr[] = {10,20,30,40};
int x = binarySearch(arr,0,3,40);
cout << x ;
}
How is it returning the correct value of the item searched for although its not even reaching the return statement.
It is reaching the base case when it is only one element in the array, but it should not reach the return statement, thus it should return garbage, but it is returning the correct index every time.
In most cases you don't return any value so you get whatever happens to be in the result register or stack slot at the time. This can work by accident, if you are unlucky.
Turn on compiler warnings and always fix them. Best to turn warnings into errors.

Error: Char 34: runtime error: addition of unsigned offset to 0x603000000070 overflowed to 0x60300000006c (stl_vector.h) (C++)

I have been trying to solve the sorted Squares leetcode problem (https://leetcode.com/explore/learn/card/fun-with-arrays/521/introduction/3240/), and I am mostly through it. However, I get the above error. Following is my code
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int start = 0;
int end = nums.size()-1;
vector<int> final(nums.size());
int finalIdx = final.size()-1;
int sqr = 0;
while(start<=end){
if (abs(nums[start])<abs(nums[end])){
sqr = nums[end]*nums[end];
final[finalIdx] = sqr;
finalIdx--;
end--;
}
if (abs(nums[start])>abs(nums[end])){
sqr = nums[start]*nums[start];
final[finalIdx] = sqr;
finalIdx--;
start++;
}
else if(abs(nums[start])==abs(nums[end])){
sqr = nums[end]*nums[end];
final[finalIdx] = sqr;
finalIdx--;
final[finalIdx] = sqr;
finalIdx--;
start++;
end--;
}
return final;
}
}
};
The issue lies in my loop condition I believe. When I change the condition to start<end, I have no compile error, but the first element of the output array (final) is always 0, which I assume is by default. However, when I try to do start<=end in order to add a condition that handles the start==end case, I get the above error. I would like to understand why this is happening so I can rectify the issue. Thanks!
First, that's not a "compile error" ; it's a runtime error (and the error message reported says as much.
That said, the issue stems from the condition of start <= end landing on the = part of that condition. Eventually that is guaranteed to happen, save for one very specific set of circumstances:
start = (end-1)
abs(num[start]) == abs(num[end])
When that happens, your code will dump two values to the output vector, and both increment start and decrement end. The start and end indexes effectively swap values, the while condition is no longer true, and the loop will now cleanly exit.
In all other circumstances start and end will eventually land on the same index. When that happens your dual-push logic will dump the same value twice into the target vector, and that is where the issue manifests. There is only one value left to push (and start and end both reference it by index). Therefore you're going to push one more value into your target vector than you have space for, and the runtime exception ensues.
The fix is simple. Stop trying to be smart about short circuiting in three different conditions when in reality you only need one and a master-else. The computational requirements are the same no matter what, and in the end all you need is this:
class Solution
{
public:
std::vector<int> sortedSquares(std::vector<int> const &nums)
{
std::vector<int> final(nums.size());
int start = 0;
int end = nums.size()-1;
int finalIdx = final.size()-1;
while(start<=end)
{
if (abs(nums[end]) < abs(nums[start]))
{
final[finalIdx--] = nums[start]*nums[start];
++start;
}
else
{
final[finalIdx--] = nums[end]*nums[end];
--end;
}
}
return final;
}
};
If you really want all three conditions in your code, it is possible, but not warranted, and the special case circumstances don't justify doing it. Regardless, see below:
class Solution
{
public:
std::vector<int> sortedSquares(std::vector<int> const &nums)
{
std::vector<int> final(nums.size());
int start = 0;
int end = nums.size() - 1;
int finalIdx = final.size() - 1;
while (start <= end)
{
if (abs(nums[start]) < abs(nums[end]))
{
final[finalIdx--] = nums[end] * nums[end];
end--;
}
else if (abs(nums[end]) < abs(nums[start]))
{
final[finalIdx--] = nums[start] * nums[start];
start++;
}
else // !(a<b || b<0) implies (a == b)
{
int sqr = final[finalIdx--] = nums[end] * nums[end];
if (end != start)
{
final[finalIdx--] = sqr;
}
--end;
++start;
}
}
return final;
}
};

What is the problem with this boolean function?

I was wondering what I may have done wrong in writing this simple function which is supposed to return true if the given number is a prime, or false if not a prime.
bool isPrime(int num)
{
if (num <= 1)
{
status = false;
}
else
{
for (int i = 1; i <= num; i++)
{
if (num % i == 0)
{
dividers++;
}
}
if (dividers == 2)
{
status = true;
}
else
{
status = false;
}
}
return status;
}
Obviously, my main looks like this:
bool isPrime(int num);
bool status;
int dividers = 0;
int main() {
isPrime(2);
if (!isPrime)
{
std::cout << "Not prime" << std::endl;
}
else
{
std::cout << "Prime" << std::endl;
}
return 0;
}
I'm a C++ beginner and I'd really appreciate it if someone could help me there and correct my logic.
Have a good day:)
The immediate problem is in this two lines:
isPrime(2);
if (!isPrime)
The first line calls the function and discards the returned value. The second line converts a pointer to the function to bool. The output of your code does not depend on what you actually do in isPrime.
That is not how you call a function and use its result!
Instead you want
if (isPrime(2)) {
or
bool isP = isPrime(2);
if (isP) { ...
As mentioned in comments, there are also problems in the implementation of isPrime, but I hope this is enough to set you back on the right track.
PS: You should get rid of the global variable status. You do not need both, the return value and a global that stores the result, and if you can choose, you should definitely go for the return value.

How to limit a decrement?

There is a initial game difficulty which is
game_difficulty=5 //Initial
Every 3 times if you get it right, your difficulty goes up to infinity but every 3 times you get it wrong, your difficulty goes down but not below 5. So, in this code for ex:
if(user_words==words) win_count+=1;
else() incorrect_count+=1;
if(win_count%3==0) /*increase diff*/;
if(incorrect_count%3==0) /*decrease difficulty*/;
How should I go about doing this?
Simple answer:
if(incorrect_count%3==0) difficulty = max(difficulty-1, 5);
But personally I would wrap it up in a small class then you can contain all the logic and expand it as you go along, something such as:
class Difficulty
{
public:
Difficulty() {};
void AddWin()
{
m_IncorrectCount = 0; // reset because we got one right?
if (++m_WinCount % 3)
{
m_WinCount = 0;
++m_CurrentDifficulty;
}
}
void AddIncorrect()
{
m_WinCount = 0; // reset because we got one wrong?
if (++m_IncorrectCount >= 3 && m_CurrentDifficulty > 5)
{
m_IncorrectCount = 0;
--m_CurrentDifficulty;
}
}
int GetDifficulty()
{
return m_CurrentDifficulty;
}
private:
int m_CurrentDifficulty = 5;
int m_WinCount = 0;
int m_IncorrectCount = 0;
};
You could just add this as a condition:
if (user words==words) {
win_count += 1;
if (win_count %3 == 0) {
++diff;
}
} else {
incorrect_count += 1;
if (incorrect_count % 3 == 0 && diff > 5) {
--diff
}
}
For example:
if(win_count%3==0) difficulty++;
if(incorrect_count%3==0 && difficulty > 5) difficulty--;
This can be turned into a motivating example for custom data types.
Create a class which wraps the difficulty int as a private member variable, and in the public member functions make sure that the so-called contract is met. You will end up with a value which is always guaranteed to meet your specifications. Here is an example:
class Difficulty
{
public:
// initial values for a new Difficulty object:
Difficulty() :
right_answer_count(0),
wrong_answer_count(0),
value(5)
{}
// called when a right answer should be taken into account:
void GotItRight()
{
++right_answer_count;
if (right_answer_count == 3)
{
right_answer_count = 0;
++value;
}
}
// called when a wrong answer should be taken into account:
void GotItWrong()
{
++wrong_answer_count;
if (wrong_answer_count == 3)
{
wrong_answer_count = 0;
--value;
if (value < 5)
{
value = 5;
}
}
}
// returns the value itself
int Value() const
{
return value;
}
private:
int right_answer_count;
int wrong_answer_count;
int value;
};
And here is how you would use the class:
Difficulty game_difficulty;
// six right answers:
for (int count = 0; count < 6; ++count)
{
game_difficulty.GotItRight();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
// three wrong answers:
for (int count = 0; count < 3; ++count)
{
game_difficulty.GotItWrong();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
// one hundred wrong answers:
for (int count = 0; count < 100; ++count)
{
game_difficulty.GotItWrong();
}
// check wrapped value:
std::cout << game_difficulty.Value() << "\n";
Output:
7
6
5
Once you have a firm grasp on how such types are created and used, you can start to look into operator overloading so that the type can be used more like a real int, i.e. with +, - and so on.
How should I go about doing this?
You have marked this question as C++. IMHO the c++ way is to create a class encapsulating all your issues.
Perhaps something like:
class GameDifficulty
{
public:
GameDifficulty () :
game_difficulty (5), win_count(0), incorrect_count(0)
{}
~GameDifficulty () {}
void update(const T& words)
{
if(user words==words) win_count+=1;
else incorrect_count+=1;
// modify game_difficulty as you desire
if(win_count%3 == 0)
game_difficulty += 1 ; // increase diff no upper limit
if((incorrect_count%3 == 0) && (game_difficulty > 5))
game_difficulty -= 1; //decrease diff;
}
inline int gameDifficulty() { return (game_difficulty); }
// and any other access per needs of your game
private:
int game_difficulty;
int win_count;
int incorrect_count;
}
// note - not compiled or tested
usage would be:
// instantiate
GameDiffculty gameDifficulty;
// ...
// use update()
gameDifficulty.update(word);
// ...
// use access
gameDifficulty.gameDifficulty();
Advantage: encapsulation
This code is in one place, not polluting elsewhere in your code.
You can change these policies in this one place, with no impact to the rest of your code.

Error: not all control paths return a value

I am writing two functions in a program to check if a string has an assigned numeric code to its structure array or if the given numeric code has an assigned string in the same structure array. Basically, if I only know one of the two, I can get the other. I wrote the following:
int PrimaryIndex::check_title_pos(std::string title) {
bool findPos = true;
if (findPos) {
for (int s = 1; s <= 25; s++) {
if (my_list[s].title == title) {
return s;
}
}
} else {
return -1;
}
}
std::string PrimaryIndex::check_title_at_pos(int pos) {
bool findTitle = true;
if (findTitle) {
for (int p = 1; p <= 25; p++) {
if (my_list[p].tag == pos) {
return my_list[p].title;
}
}
} else {
return "No title retrievable from " + pos;
}
}
However, it says not all control paths have a return value. I thought the else {} statement would handle that but it's not. Likewise, I added default "return -1;" and "return "";" to the appropriate functions handling int and string, respectively. That just caused it to error out.
Any idea on how I can keep this code, as I'd like to think it works but cant test it, while giving my compiler happiness? I realize through other searches that it sees conditions that could otherwise end in no returning values but theoretically, if I am right, it should work fine. :|
Thanks
In the below snippet, if s iterates to 26 without the inner if ever evaluating to true then a return statement is never reached.
if (findPos) {
for (int s = 1; s <= 25; s++) {
if (my_list[s].title == title) {
return s;
}
}
}