In the following program, I declare a global variable (adj_matrix) for the purpose of using it in different functions. It is defined in another function (init_matrix).
I tested the program with the test case 3 1 2 and received a segmentation fault.
3 1 2
YES
Segmentation fault: 11
The surprising part is, that when I uncomment the cout line in the construct_matrix function, the segmentation fault disappears.
This looks like the case of undefined behavior to me but I'm unable to figure out why and where it occurs. Please help.
Following is the program:
#include <iostream>
#include <vector>
using namespace std;
vector<vector<int> > adj_matrix;
void init_matrix(int size, int val)
{
adj_matrix.reserve(size);
for (int i = 0; i < size; ++i)
{
adj_matrix[i].reserve(size);
for (int j = 0; j < size; ++j)
{
if(i == j)
adj_matrix[i][i] = 0;
else
adj_matrix[i][j] = val;
}
}
}
void construct_matrix(int size, int k, int val)
{
// k denotes how many components we want
for (int i = k - 1; i < size - 1; ++i)
{
adj_matrix[i][i + 1] = val;
adj_matrix[i + 1][i] = val;
// Uncommenting the following line resolves the seg-fault error
// cout << i << endl;
}
}
void print_matrix(int size)
{
for (int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j)
cout << adj_matrix[i][j];
cout << endl;
}
}
int main()
{
int n, a, b;
cin >> n >> a >> b;
/*
The solution uses the fact that atleast one of G or G complement is always connected.
In cases where we have to show both are connected (not possible when n is 2 or 3),
we draw a simple graph connected v1 v2 v3...vn. The complement will be also connected (n != 2 and 3)
*/
if(a == 1 && b == 1)
{
if(n == 2 || n == 3)
cout << "NO" << endl;
else
{
cout << "YES" << endl;
init_matrix(n, 0);
construct_matrix(n, 1, 1);
print_matrix(n);
}
}
else if(a == 1)
{
cout << "YES" << endl;
init_matrix(n, 1);
construct_matrix(n, b, 0);
print_matrix(n);
}
else if(b == 1)
{
cout << "YES" << endl;
init_matrix(n, 0);
construct_matrix(n, a, 1);
print_matrix(n);
}
else
cout << "NO" << endl;
return 0;
}
For ones interested in the problem this is a solution to, visit here.
PS: I've checked the bounds in the for loop in my functions, and they are correct. If this wasn't the case, the program will throw a segmentation fault regardless of the cout line.
The reason / one of reasons of undefined behavior in this code is using operator[] to access elements of vector that are not yet created.
From http://www.cplusplus.com/reference/vector/vector/operator[]/:
A similar member function, vector::at, has the same behavior as this operator function, except that vector::at is bound-checked and signals if the requested position is out of range by throwing an out_of_range exception.
Portable programs should never call this function with an argument n that is out of range, since this causes undefined behavior.
reserve doesn't create new elements of the vector. It just ensures that the vector has allocated enough memory for them. If you want to create new elements which you can access, use resize. (https://stackoverflow.com/a/7397862/3052438)
I also recommend to double check all you vector accesses for out of bound indexes, after you fix the first problem.
adj_matrix.reserve(size); Does not create any elements, but just reserves the size of the vector. As such adj_matrix[i].reserve(size); is undefined behaviour when i is greater than adj_matrix.size()
Related
really new to C++, trying to instantiate some basic algorithms with it. Having trouble returning the correct result for selection sort. Here is my code
#include <iostream>
#include <array>
#include <vector>
using namespace std;
// Selection Sort :
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
return m;
}
}
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void selectionSort(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); ++i)
{
int min = findMin(arr, i);
swap(arr[i], arr[min]); // Assume a correct swap function
}
}
}
void print(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); i++)
{
cout << arr[i] << "";
cout << endl;
}
}
}
int main()
{
vector<int> sort;
sort.push_back(2);
sort.push_back(1);
sort.push_back(7);
sort.push_back(4);
sort.push_back(5);
sort.push_back(3);
print(sort);
cout << "this was unsorted array";
cout << endl;
cout << findMin(sort, 0);
cout << "this was minimum";
cout << endl;
selectionSort(sort);
print(sort);
}
I am getting the following results:
comparison_sort.cpp:20:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
}
^
1 warning generated.
2
1
7
4
5
3
this was unsorted array
1
this was minimum
1
2
4
5
3
0
My question is: What is causing this control path error? Why is the "7" here being replaced with a "0"?
Thanks in advance! Sorry for the noob question.
I have reviewed all my current functions and nothing seems to explain why the 7 is replaced with a 0. I have tried multiple integers and it looks like the maximum number is always replaced.
The warning is very real, and it alludes to the problem that's breaking your sort as well.
You are currently returning m inside your loop body. What that means is that if the loop is entered, then the function will return m on the very first time around the loop. It only has a chance to check the first element.
And of course, if a is the last index of the array, then the loop will never execute, and you will never explicitly return a value. This is the "control path" which does not return a value.
It's quite clear that you've accidentally put return m; in the wrong place, and even though you have good code indentation, some inexplicable force is preventing you from seeing this. To fix both the warning and the sorting issue, move return m; outside the loop:
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
}
return m;
}
#include <bits/stdc++.h>
using namespace std;
int freq[101034];
int main() {
int n;
cin >> n;
set<int> st;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
freq[x]++;
st.insert(x);
}
while (!st.empty()) {
for (auto x : st) {
if (freq[x] <= 0) {
st.erase(x);
continue;
}
cout << x << ' ';
freq[x]--;
}
cout << '\n';
}
return 0;
}
The problem I have tried to solve: Given an array of integers n up to 10^5 and each element up to 10^5, the task is to print the array sorted without repetition, then delete the array elements that are printed, then repeat until the array is empty.
For instance if array [1, 1, 2, 3, 4, 4]
This should be printed
1 2 3 4
1 4
I maintained a frequency array to hold each element frequency and the code above causes runtime error. The program crashes. I've tried to remove the if statement, the program runs normally, but goes to infinite loop for sure! I really can't figure why the if causes runtime error.
The issue is in this snippet:
while (!st.empty()) {
for (auto x : st) {
if (freq[x] <= 0) {
st.erase(x);
continue;
}
cout << x << ' ';
freq[x]--;
}
cout << '\n';
}
The range-based for loop uses iterators in the back (see this for more details). When you erase x from st the loop iterator (pointing to x) becomes invalid (this means that you mustn't use it anymore), but in the snippet above, it still gets incremented at the end of the loop in the background, that result undefined behavior, hence the runtime error.
Take a look at this page to see how you should implement it properly. Applying the practice of the previous link to your code:
while (!st.empty()) {
for (auto it = cbegin(st); it != cend(st);) {
auto x = *it;
if (freq[x] <= 0) {
it = st.erase(it);
} else {
++it;
cout << x << ' ';
freq[x]--;
}
}
cout << '\n';
}
I have the fallowing code. I read the guide for what a segmentation fault is, but I'm not 100% sure where its actually happening within my code. It works until I start working with the dynamic array (histogram), more specifically at the //set all initial values to be zero. Within that mess after I'm not sure. Thanks!
The instructor asked to "Use a dynamic array to store the histogram.", Which I think is my issue here.
-Solved-
thanks for the help, the error was in how I initialized the array pointer
rather than
const int hSize = 10;
IntArrayPtr histogram;
histogram = new int[hSize];
I used
const int hSize = 10;
int hValues[hSize] = { 0 };
IntArrayPtr histogram;
histogram = hValues;
Which worked as the instructor wanted.
#include <iostream>
#include <vector>
using namespace std;
typedef int* IntArrayPtr;
int main() {
vector<int>grades;
int newGrade;
cout << "Input grades between 0 and 100. Input -1 to calculate histogram: " << endl;
cin >> newGrade;
grades.push_back(newGrade);
while (newGrade > 0) {
cin >> newGrade;
while (newGrade > 100) {
cout << "less than 100 plz: ";
cin >> newGrade;
}
grades.push_back(newGrade);
}
grades.pop_back();
int size = grades.size();
cout << "Calculating histogram with " << size << " grades." << endl;
//Create dynamic array for the histogram of 10 sections.
const int hSize = 10;
IntArrayPtr histogram;
histogram = new int[hSize];
}
//Make the historgram
int stackValue = 0;
for (int j = 0; j < hSize; j++) {
//Loop through the grade vector slots
for (int i = 0; i < size; i++) {
int testValue = grades[i];
//If the grade at the index is between the stack values of the histogram add one to the value of the slot
if (testValue > stackValue && testValue < stackValue + 10) {
histogram[j]++;
}
}
//After looping through the vector jump up to the next histogram slot and corresponding stack value.
stackValue += 10;
}
//Histogram output. Only output the stacks with values
for (int i = 0; i < 10; i++) {
if (histogram[i] != 0) {
cout << "Number of " << (i + 1) * 10 << "'s: " << histogram[i];
}
}
return 0;
}
Working Code:
#include <iostream>
#include <vector>
using namespace std;
typedef int* IntArrayPtr;
int main() {
vector<int>grades;
int newGrade;
cout << "Input grades between 0 and 100. Input -1 to calculate histogram: " << endl;
cin >> newGrade;
grades.push_back(newGrade);
while (newGrade > 0) {
cin >> newGrade;
while (newGrade > 100) {
cout << "less than 100 plz: ";
cin >> newGrade;
}
grades.push_back(newGrade);
}
grades.pop_back();
int size = grades.size();
cout << "Calculating histogram with " << size << " grades." << endl;
//Create dynamic array for the histogram of 10 sections.
const int hSize = 10;
int hValues[hSize] = { 0 };
IntArrayPtr histogram;
histogram = hValues;
//Make the historgram
int stackValue = 0;
for (int j = 0; j < hSize; j++) {
//Loop through the grade vector slots
for (int i = 0; i < size; i++) {
int testValue = grades[i];
//If the grade at the index is between the stack values of the histogram add one to the value of the slot
if (testValue > stackValue && testValue < stackValue + 10) {
histogram[j]++;
}
}
//After looping through the vector jump up to the next histogram slot and corresponding stack value.
stackValue += 10;
}
//Histogram output. Only output the stacks with values
for (int i = 0; i < 10; i++) {
if (histogram[i] != 0) {
cout << "Number of " << (i + 1) * 10 << "'s: " << histogram[i] << endl;
}
}
return 0;
}
histogram is a pointer, not an array.
While
int histogram[hSize] = {0};
would create a zero-initialised array, your
histogram = { 0 };
does not set any elements to zero (it couldn't, because histogram points to one int, not many).
The braces are ignored – a pretty confusing behaviour inherited from C – and it is equivalent to
histogram = 0;
that is,
histogram = nullptr;
You want
int* histogram = new int[hSize]();
The parentheses value-initialises the array, and in turn its elements.
Value-initialising integers sets them to zero.
(By the way: the habit of typedeffing away asterisks causes more problems than it solves. Don't do it.)
Seg faults are problems with accessing regions of memory you don't have access to, so you need to look at your use of pointers. It often means you have a pointer with a bad value that you just dereferenced.
In this case, the problem is this line:
histogram = { 0 };
This is not setting the histogram values to zero as you think: it's resetting the historgram pointer to zero. Then you later dereference that pointer causing your SegFault (note that this line doesn't even compile with clang, so your compiler isn't helping you any on this one).
Changing that line to:
memset(histogram, 0, hSize);
Will sort the problem in this case.
More generally, to diagnose a segfault there are two tricks I use regularly (though avoidance is better than cure):
Run the program under a debugger: the debugger will likely stop the program at the point of the fault and you can see exactly where it failed
Run the program under Valgrind or similar - that will also tell you where the error surfaced but in more complex failures can also tell you where it was caused (often not the same place).
I am creating a program that rewrites an array with values from a file. I have linked the code below. When running the file I get the error "Run-time check failure, stack around 'arr' variable was corrupted.
Also, the output of the program returns all the array locations with the same number,
arr[0] = -858993460
The numbers in the file, separated by a line are:
12
13
15
#include<iostream>;
#include<fstream>;
using namespace std;
template <class T>
void init(T * a, int size, T v)//done
{
for (int i = 0; i < size; i++)
{
a[size] = v;
}
}
bool getNumbers(char * file, int * a, int & size)//not done
{
int count = 0;
ifstream f(file);
while (f.good() == true && count < 1)
{
f >> a[count];
count++;
}
if (size > count)
{
return true;
}
else if (size < count)
{
return false;
}
}
void testGetNumbers()
{
int arr[5];
int size = 5;
cout << "Testing init and getNumbers." << endl;
init(arr, 5, -1);
cout << "Before getNumbers: " << endl;
for (int i = 0; i < size; i++)
{
cout << "arr[" << i << "] = " << arr[i] << endl;
}
if (getNumbers("nums.txt", arr, size))
{
cout << size << " numbers read from file" << endl;
}
else
{
cout << "Array not large enough" << endl;
}
cout << "After getNumbers: " << endl;
for (int i = 0; i < size; i++)
{
cout << "arr[" << i << "] = " << arr[i] << endl;
}
cout << endl;
}
int main()
{
testGetNumbers();
return 0;
}
This line in the first loop looks like having error.
a[size] = v;
It causes out of array bound access and memory/stack corruption. It should be
a[i] = v;
Starting with the main function, the line
return 0;
... is not necessary because that's the default return value for main. I would remove it, some people insist on having it, I think most people don't care. But it's always a good idea to be fully aware of what the code expresses, implicitly or explicitly, so: returning 0 expresses that the program succeeded.
For an explicit main return value I recommend using the names EXIT_SUCCESS and EXIT_FAILURE from the <stdlib.h> header.
Then it's much more clear.
main calls testGetNumbers, which, except for an output statement, starts like this:
int arr[5];
int size = 5;
init(arr, 5, -1);
As it happens the init function is has Undefined Behavior and doesn't fill the array with -1 values as intended, but disregard. For now, look only at the verbosity above. Consider writing this instead:
vector<int> arr( 5, -1 );
Using std::vector from the <vector> header.
Following the call chain down into init, one finds
a[size] = v;
That attempts to assign value v to the item just beyond the end of the array.
That has Undefined Behavior.
Should probably be
a[i] = v;
But as noted, this whole function is redundant when you use std::vector, as you should unless strictly forbidden by your teacher.
Back up in testGetNumbers it proceeds to call getNumbers, in that function we find
ifstream f(file);
while (f.good() == true && count < 1)
{
f >> a[count];
count++;
}
Generally one should never use f.good() or f.eof() in a loop condition: use f.fail(). Also, ~never compare a boolean to true or false, just use it directly. Then the loop can look like this:
ifstream f(file);
while (!f.fail() && count < 1)
{
f >> a[count];
count++;
}
Tip: in standard C++ you can write ! as not and && as and. With the Visual C++ compiler you have to include the <iso646.h> header to do that.
Disclaimer: the fixes noted here do not guarantee that the loop is correct for your intended purpose. Indeed the increment of count also when the input operation fails, looks probably unintended. Ditto for the loop limit.
The function continues (or rather, ends) with
if (size > count)
{
return true;
}
else if (size < count)
{
return false;
}
This has a big problem: what if size == count? Then the execution continues to fall off the end of the function without returning a value. This is again Undefined Behavior.
I leave it to you to decide what you want the function to return in that case, and ensure that it does that.
In your init function...
template <class T>
void init(T * a, int size, T v)//done
{
for (int i = 0; i < size; i++)
{
a[size] = v;
}
}
Nope:
a[size] = v;
Yup:
a[i] = v;
I'm having an issue with a recursive sorting assignment in C++. Unfortunately, we've been assigned to do it in a very specific way, but I cannot seem to manage to get it to do what I want, and since I'm not used to recursion, I can't follow it well to trouble shoot. The error that I'm getting is Unhandled exception at 0x77d915fe in SortFinal.exe: 0xC0000005: Access violation. Presumably this is coming somehow from the a[] array used within the sort function. I'm new to this site so forgive me if the organization is terrible, but here's my code as it currently stands:
#include <iostream>
using namespace std;
// prototypes
void sort(int a[], int i, int j);
int main() {
int x[4] = {3, 1, 5, 2};
for (int count = 0; count < 4; count++) {
cout << x[count] << ": ";
}
cout << endl;
sort(x, 0, 4);
for (int count = 0; count < 4; count++) {
cout << x[count] << ": ";
}
cout << endl;
system("pause");
return 0;
}
void sort(int a[], int i, int j) {
int first;
if (j > i) {
int index = i + 1;
bool done = false;
first = a[i];
sort(a, i + 1, j);
for (!done && index <= j; index++;) {
if (first < a[index]) {
a[index - 1] = a[index];
} else {
a[index - 1] = first;
done = true;
}
}
if (!done && index > j) {
a[index - 1] = first;
}
}
}
The line with the problem is: for (!done && index <= j; index++;) { in the for loop the first block is initialization, the second stop condition and the third is increment, in you case you are putting stop condition as initialization and increment as stop condition, changed by for (; !done && index <= j; index++) {. Please take always good look before posting in SO. Any compiler (and I mean ANY) would catch this error with a error message good enough for you to figure out the problem. In GCC 4.9.1 was:
E:\test.cpp: In function 'void sort(int*, int, int)':
E:\test.cpp:34:20: warning: statement has no effect [-Wunused-value]
for (!done && index <= j; index++;) {
^
Compile always with all warnings enable (-Wall in GCC and Clang, select at least level 4 in Visual C++), the compiler would help you to fix a lot (valid code that are bugs).