Function not returning/Program exiting - c++

I'm writing code for a dynamic solution to the knapsack problem, with the values, weight, etc being read in from a file. After writing the knapsack function code, it seems that it will not return when I try to test just the result being returned.
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
//knapsack here
int knapsack(int cap, int weight[], int value[], int n)
{
int** K = new int* [n + 1];
int j = 0;
int l = 0;
for (int i = 0; i < n + 1; i++)
{
K[i] = new int[cap + 1];
}
for (j = 0; j <= n; j++)
{
for (l = 0; l <= cap; l++)
{
if (j == 0 || l == 0)
K[j][l] = 0;
else if (weight[j - 1] <= l)
{
K[j][l] = max(weight[j - 1] + K[j - 1][l - weight[j - 1]], K[j - 1][l]);
}
else
{
K[j][l] = K[j - 1][l];
}
}
}
return K[j][l]; <--- Exception thrown
}
int main(void)
{
string filename;
ifstream infile;
int capacity = 0;
int items = 0;
//Get input file from user and open
cout << "Enter the file name: ";
cin >> filename;
infile.open(filename);
//Get capacity and number of items
infile >> capacity >> items;
//Initialize arrays
int* w = new int[items];
int* v = new int[items];
//Read values from file into arrays
for (int i = 0; i < items; i++)
{
infile >> w[i];
infile >> v[i];
}
//Solution Table
cout << endl << endl << endl;
cout << "Solution Table:" << endl;
//Testing purposes
cout << knapsack(capacity, w, v, items) << endl << "Test";
infile.close();
return 0;
}
Everything that is printed in main will print up until the final cout (after the Solution Table: line prints). The program will then pause for a moment and exit with an error code (C:\Users\Me\source\repos\Project3\Debug\Project3.exe (process 3028) exited with code -1073741819). I haven't been able to figure out a way to get a return from the function yet, and the exiting is something I haven't been able to figure out why it is occurring either.
EDIT: On using the debugger, an exception is being thrown when running through the knapsack function on the return:
Exception thrown at 0x006BB128 in Project3.exe: 0xC0000005: Access violation reading location 0xFDFDFE0D

int** K = new int* [n + 1];
// ...
K[i] = new int[cap + 1];
// ...
for (j = 0; j <= n; j++)
{
for (l = 0; l <= cap; l++)
{
// ...
}
}
// j == n + 1
// l == cap + 1
return K[j][l]; <--- Exception thrown because of out of bounds access to K
K is an array of length n + 1, which means its elements are accessed using indices from O to (inclusive) n. n + 1 is an out of bound access. At the end of the (outer) for loop the variable j is n + 1. You make the same error with the inner loop and the second operator[].
That being said, it helps a lot if you:
Ditch the idea of "2d arrays". These arrays of pointers to arrays are difficult to handle and have a heavy performance impact (messed up memory locality). They are (probably) only useful when the "full" array (e.g. the 2D table flattened into a single array) is too large to reliably get successfully allocated.
Use std::vector. There is really no point working with raw arrays. Except for learning. And in that case: delete[] the memory you allocate!
Why is "using namespace std;" considered bad practice?

C-style strings might cause problems. They are hard to maintain and track. I support Jesper's idea here.
Also, I do not see that you are freeing the memory after you are done with the pointers which will create memory leakage.

Related

c++ runtime error when using vectors push back and iterator

Hi I'm trying to solve a algorithm problem and when I submit my code on an online judge I keep on getting a runtime error. I have no idea why it is happening.
Here is the problem that I'm trying to solve.
The code is as follows. It works fine for the sample input and outputs in visual studio. I haven't yet met inputs and outputs that does not work well or actually meet the runtime error. Only the online judge is giving the runtime error so I can't figure out why.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
int m;
int c1;
int c2;
cin >> n >> m >> c1 >> c2;
vector<int> p = {};
vector<int> q = {};
for (int i = 0; i < n; ++i)
{
int temp;
cin >> temp;
p.push_back(temp);
}
for (int i = 0; i < m; ++i)
{
int temp;
cin >> temp;
q.push_back(temp);
}
vector<int> distance = {};
for (int i = 0; i < p.size(); ++i)
{
for (int j = 0; j < q.size(); ++j)
{
distance.push_back(abs(p[i] - q[j]) + abs(c1 - c2));
}
}
sort(distance.begin(), distance.end());
int min = distance[0];
int count = 0;;
for (int i = 0; i < static_cast<int>(distance.size()); ++i)
{
if (distance[0] == distance[i])
count++;
else
break;
}
cout << min << " " << count << endl;
return 0;
}
If n and m are both the maximum allowed value of 500,000 then distance will have 500,000 * 500,000 elements which will use 1TB of memory. Due to vector growing as you push_back you could actually need around 2TB of memory in total. The online judge presumably doesn't allow you to use this much memory.
If you rethink your algorithm to not store the values of distance it will probably work.
You should lways use reserve on std::vector if you know the size in advance as it should cause the vector to allocate exactly the right amount of memory and avoid copying to new blocks of memory as the vector grows.

Locating a Segmentation Fault

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).

bad alloc exception when trying to resolve BFS challenge on HackerRank

So i was trying to make the challage: Breadth First Search: Shortest Reach on HackerRank, but i keep getting the bad alloc exception when the tests have great numbers of node/edges. The program works on the first test, so i don't think, it's something wrong with the implementation.
So here is the implementation:
(sorry for the indentation , my first question)
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <limits.h>
using namespace std;
int main() {
//test numbers
int t;
//the cost
int cost = 6;
cin >> t;
//for each test
for (int nt = 0; nt < t; ++nt) {
int n, e;
int snode;
queue <int> *que = new queue<int>();
//read the node/edges
cin >> n >> e;
//distance/visited/parents arrays/adjlist vector
int dist[n + 1] = {-1};
bool visited[n + 1] = {false};
int parents[n + 1] = {-1};
vector< vector<int> > adjList(n + 1);
//read into the adjlist, unoriented graph, each edge has 6 weight
for (int ne = 0; ne < e; ++ne) {
int x, y;
cin >> x >> y;
adjList[x].push_back(y);
adjList[y].push_back(x);
}
//read the starting node
cin >> snode;
dist[snode] = 0;
//do actual bfs
que->push(snode);
visited[snode] = true;
while(!que->empty()) {
int c_node = que->front();
que->pop();
for (int i = 0; i < adjList[c_node].size(); ++i) {
if (visited[adjList[c_node].at(i)] == false) {
que->push(adjList[c_node].at(i));
parents[adjList[c_node].at(i)] = c_node;
dist[adjList[c_node].at(i)] = dist[parents[adjList[c_node].at(i)]] + cost;
visited[adjList[c_node].at(i)] == true;
}
}
}
//print at output the distance from the starting node to each other node
//if unreachable, print -1
for (int i = 1; i < n + 1; ++i) {
if (i == snode) {
} else if (dist[i] == 0 && i != snode) {
cout << "-1 ";
} else {
cout << dist[i] << " ";
}
}
cout << "\n";
}
return 0;
}
Am i doing something wrong, i haven't seen anyone else complain on this matter in the discussion section of the site.
How can i avoid the exception to be thrown and from where does it come?
Thank you!
I don't know, exactly, what is the cause of your exception; and I don't know ho to reproduce your problem because depends (I suppose) from the input values. A lot of input values, I suppose.
But I see some weak points (IMHO) of your code, so I try to point your attention to them.
1) you alloc a std::queue in your for cycle
queue <int> *que = new queue<int>();
but you never free it; it's a waste of memory
2) you're using C-style variable-length arrays
int dist[n + 1] = {-1};
bool visited[n + 1] = {false};
int parents[n + 1] = {-1};
They aren't valid C++ standard code. I suggest you the use of standard containers (std::vector or std::queue).
3) you're initializing your C-style variable-length arrays with a initializers lists with only an element (-1 or false). I suppose your intention was initialize all n+1 elements with -1 and false. But this syntax initialize only the first element of the array with -1 and false.
If you want to initialize all n+1 element to -1 and false, the solution is (again) use standard containers; by example
std::vector<int> dist(n+1, -1);
std::vector<bool> visited(n+1, false);
std::vector<int> parents(n+1, -1);
4) you access arrays without bounds checking. By example:
cin >> snode;
dist[snode] = 0;
where snode is a int variable; if you insert a negative value, or a value over n, you write dist out of its bounds, devastating the memory. This, I suppose, can explain your "bad alloc exception".
Suggestion: use standard containers (again) instead of C-style array and use at() (that perform bounds checking) instead []; so
cin >> snode;
dist.at(snode) = 0;
5) sorry for my bad English (ok, I'm joking: this isn't one of your weak points; this is one of mine).

Heap Corruption Error while doing bubble sort using dynamic arrays

Hi i am trying to create a bubble sort using dynamic arrays, the code seems to work but throws an run time error : HEAP Corruption Detected(since i am deleting dynamic arrays in the ...i donot understand why i am getting such an error). Also, the last two elements in the given array get sorted but i get the address displayed for the last element . As i am trying to learn dynamic arrays on my own.Kindly help me understand the error. Thanks in advance !!!
Array = {125,12,2,36,19}
#include "stdafx.h"
#include <iostream>
using namespace std;
void bubblesort(int* a, int length); // for bubble sort//
int _tmain(int argc, _TCHAR* argv[])
{
int size;
cout << " enter the size of array: " << endl;
cin >> size;
int* a = new int[size];
cout << "enter the elements in an array: " << endl;
for (int i = 0; i < size; i++)
cin >> *(a+i);
bubblesort(a, size);
delete[] a;
a = NULL;
return 0;
}
void bubblesort(int* a, int length)
{
int temp = 0;
for (int i = 0; i < length; i++)
{
if (a[i] > a[i+1])
{
temp = a[i+1];
a[i+1] = a[i];
a[i]= temp;
}
}
for (int i = 0; i < length; i++)
{
cout << " The elements are : " << endl;
cout << a[i] << endl;
}
}
As (it was) mentioned in the comments, you're reading outside the array.
a[i + 1] = a[i]; //When i == length - 1, this is UB
In the last iteration of the for loop, you'll overwrite whatever is after the end of the array. An array a[length] is only valid from 0 through length - 1.
Also, your bubble sort only runs once, while it is supposed to constantly run until all items are sorted.
On a subjective note, *(a+i) is identical to, but less readable than, a[i].

Vector equilibrium point(s) function in C++

So I wanted to clean the rust off my C++ skills and thought I'd start with something fairly simple. An equilibrium point in a vector A of size N is a point K, such that: A[0] + A[1] + ... + A[K−1] = A[K+1] + ... + A[N−2] + A[N−1]. The rationale behind the function algorithm is simple: Check each consecutive element of the vector and compare the sum of the elements before said element with the sum of the elements after it and if they are equal, output the index of that element. While it sounds simple (and I imagine that it is) it turned out to be harder to implement in reality. Here's what the code looks like:
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
void EquilibriumPoint(std::vector<int> &A);
void VectorPrint(std::vector<int> &V);
void main()
{
int input;
std::vector<int> Vect1;
cout << "Input the vector elements" << endl;
while (cin >> input)
Vect1.push_back(input);
VectorPrint(Vect1);
EquilibriumPoint(Vect1);
}
void EquilibriumPoint(std::vector<int> &A)
{
for (int it = 0; it != A.size(); ++it)
{
int lowersum = 0;
int uppersum = 0;
for (int beg = 0; beg != it; ++beg) lowersum += A[beg];
for (int end = it + 1; end != A.size(); ++end) uppersum += A[end];
if (uppersum == lowersum) cout << it;
}
}
void VectorPrint(std::vector<int> &V)
{
for (int i = 0; i != V.size(); ++i)
cout << V[i] << endl;
}
As you can see I threw in a print function also for good measure. The problem is that the program doesn't seem to execute the EquilibriumPoint function. There must be a problem with the logic of the implementation but I can't find it. Do you guys have any suggestions?
cin >> input
always returns true for you - so IMHO you have an endless loop. You need to stop collecting elements at some point, for instance
int input = 1
while (input)
{
cin >> input;
Vect1.push_back(input);
}
Will accept all elements that are not zero, when zero arrives, it will end the vector and run your function.
Or you can first input the number of elements (if you want to include zeros), example:
int count;
cin >> count
for (int i = 0; i < count; ++i)
{
cin >> input;
Vect1.push_back(input);
}
I didn't check the rest of the code, though. One problem at a time.