C++ Vague behavior of uninitialized variable [duplicate] - c++

This question already has answers here:
Default variable value
(10 answers)
Closed 7 years ago.
The below code behaves as if I have initialized variable res to 0, if I uncomment the lines above the first time I used it.
int t, mi,cur,n,res;
scanf("%d",&t);
while(t-- && scanf("%d",&n) == 1)
{
for (int i = 1; i <= n; ++i)
{
scanf("%d",&h[i]);
}
for (int i = 1; i <= n; ++i)
{
scanf("%d",&k[i]);
}
for (int i = 0; i < 1001; ++i)
dp[0][i] = INF;
for (int i = 0; i < 501; ++i)
dp[i][0] = 0;
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= 2*n; ++j)
{
dp[i][j] = dp[i-1][j];
if(j >= k[i-1])
dp[i][j] = min(dp[i-1][j],1 + dp[i][j-k[i-1]]);
}
}
// The lines below.
//for (int i = 0; i <= n; ++i)
//{
// for (int j = 0; j <= 2*n; ++j)
// {
// printf("%d ", dp[i][j]);
// }
// printf("\n");
//}
for (int i = 1; i <= n; ++i)
{
res += dp[n][2*h[i]];
}
printf("%d\n", res);
When I print the value of res with the lines commented, it gives me garbage value, but when I uncomment it, it gives me the expected value. I don't know the advanced concepts of the language. Why this happens?

dp[0][*] and dp[*][0] are not initialized as you fill your array starting at index 1.
Then, if h[i] is 0, you will definitely copy an unitialized value to res.
The advanced concepts of the language in this case is just that uninitialized variables leads to undefined behaviour and should not be used. See Default variable value (as commented by Kelvin Lai).
So you may accept that and don't try to figure out why printing the values fix the problem....because there is no point trying to determine how undefined behaviours are working...;-)
Note: The fact that comented lines in your post fixe the problem may be compiler/platform/configuration specific. It's just a kind of corner case that fixes the issue of your uninitialized variables being used when they should not...

Related

Segmentation fault - trying to pass matlab code to c ++

I'm trying to pass a code that is in matlab for c ++ but it is giving segmentation fault (core dumped), can someone help me please?
Code in MATLAB
function strip = strips(strip,n,number_pixel)
se = strel('square', 3);
strip=imdilate(strip, se);
strip = imfill(strip);
[m1,n1] = size(strip);
vet=0;
for j=1:n1
for i=1:m1
if strip(i,j)==0
vet=vet+1;
end
end
aux(j)=vet;
vet=0;
end
limite=uint8(number_pixel/4);
for i=1:n1
if aux(i) < limite
strip(:, i)=1;
end
if aux(i) >= limite
strip(:, i)=0;
end
end
end
Code in C++
Mat strips(Mat strip, int n, int number_pixel){
int vet = 0;
int limite = (number_pixel/4);
int v[strip.cols];
dilate(strip, strip, getStructuringElement(MORPH_ELLIPSE, Size(3,3)));
strip = imfill(strip);
int n1 = strip.cols;
int m1 = strip.rows;
for (int j = 0; j < n1; j++){
for (int i = 0; i < m1; i++){
if(strip.at<uchar>(i, j) == 0){
vet += 1;
}
}
v[j] = vet;
vet = 0;
}
for (int i = 0; i < n1; i++){
int j;
if (v[i] < limite){
strip.at<uchar>(i, j) = 1;
}
if (v[i] >= limite){
strip.at<uchar>(i, j) = 0;
}
}
}
I already implemented the functions as imfill, I think my error is in the loop, but I can't find
It is very hard to tell what the problem is, when not having a fully working example. One obvious problem with your code is, that you use j uninitialized in your second loop:
for (int i = 0; i < n1; i++){
int j;
if (v[i] < limite){
strip.at<uchar>(i, j) = 1; // <- uninitialized j is used
}
//...
}
This is undefined behavior and basically everything could happen. j allocates memory but does not have a specific value. See this answer:
Local variables get their initial values from whatever random data is in the stack space they occupy at that moment.
That is j could be a very large integer and you try to access a value out of bounds. Or using j itself causes the error. As I said, the behavior is undefined.
EDIT I also think the second part of your code should be changed. strip(:,i)=1 sets the ith column of the 2D array to 1. Assuming that strip.at<uchar>(i, j) returns only a reference to a single value, your c++ code should be something like this:
for (int i = 0; i < n1; i++){
if (v[i] < limite){
// go through all rows and set the i-th column to 1.
for (int j = 0; j < m1; ++j)
strip.at<uchar>(j, i) = 1;
}
//...
}

Counting Sort in C++

I am trying to implement the Counting Sort in C++ without creating a function. This is the code that I've written so far, but the program doesn't return me any values. It doesn't give me any errors either. Therefore, what is wrong?
#include <iostream>
using namespace std;
int main()
{
int A[100], B[100], C[100], i, j, k = 0, n;
cin >> n;
for (i = 0; i < n; ++i)
{
cin >> A[i];
}
for (i = 0; i < n; ++i)
{
if (A[i] > k)
{
k = A[i];
}
}
for (i = 0; i < k + 1; ++i)
{
C[i] = 0;
}
for (j = 0; j < n; ++j)
{
C[A[j]]++;
}
for (i = 0; i < k; ++i)
{
C[i] += C[i - 1];
}
for (j = n; j > 0; --j)
{
B[C[A[j]]] = A[j];
C[A[j]] -= 1;
}
for (i = 0; i < n; ++i)
{
cout << B[i] << " ";
}
return 0;
}
It looks like you're on the right track. You take input into A, find the largest value you'll be dealing with and then make sure you zero out that many values in your C array. But that's when things start to go wrong. You then do:
for (i = 0; i < k; ++i)
{
C[i] += C[i - 1];
}
for (j = n; j > 0; --j)
{
B[C[A[j]]] = A[j];
C[A[j]] -= 1;
}
That first loop will always go out of bounds on the first iteration (C[i-1] when i=0 will be undefined behavior), but even if it didn't I'm not sure what you have in mind here. Or in the loop after that for that matter.
Instead, if I were you, I'd create an indx variable to keep track of which index I'm next going to insert a number to (how many numbers I've inserted so far), and then I'd loop over C and for each value in C, I'd loop that many times and insert that many values of that index. My explanation may sound a little wordy, but that'd look like:
int indx = 0;
for(int x = 0; x <= k; x++) {
for(int y = 0; y < C[x]; y++) {
B[indx++] = x;
}
}
If you replace the two loops above with this one, then everything should work as expected.
See a live example here: ideone

Stack Smashing Error While Working with CStrings

I am working on a small project and I am absolutely stuck. The purpose of the function I'm working on is to rearrange and change a Cstring based on a few preset rules. Where my issue lies is within the second portion of my swapping algorithm I came up with.
for(int i = 0; i < len; i++)
{
if(sentence[i] == SPACE)
{
space++;
spacePlace[counter] = i;
counter++;
}
}
for(int i = 0; i < space; i++)
{
if(i == 0)
{
count2 = 0;
for(int h = 0; h < 20; h++)
{
temp1[h] = NUL;
temp2[h] = NUL;
}
for(int j = 0; j < spacePlace[0]; j++)
temp1[j] = sentence[j];
for(int m = spacePlace[0]; m < spacePlace[1]; m++)
{
temp2[count2] = sentence[m];
count2++;
}
.
.
.
the first for loops executes perfectly and the output is great, but the second for loop always messes up and ends up sending me a stack smashing error. For more reference, sentence is a cstring passed to the function, and temp1 and temp2 are also cstrings. Any help or points in the right direction would be a godsend. Thanks!

How can I not allow an element in an array to not increment if it was already incremented on that run in the loop?

I am trying to get the summary of CFG with given input. I have to list the terminals with the count of how many times it appears in the rule. However, I'm having trouble with it counting multiple terminals on the same rule.
for (int i = 0; i < cfg.size(); i++)
{
for (int j = 0; j < cfg[i].size(); j++)
{
for (int k = 0; k < terminal.size(); k++)
{
if (strcmp(cfg[i][j].c_str(), terminal[k].c_str()) == 0)
{
//TO-DO if counter[k] already incremented do not increment counter[k] again
counter[k]++;
break;
}
}
}
}
For example if the rule is
Z -> a b b b
It will return 3 for b when the correct answer would be 1.
Any help on how I can how I can leave that rule after it has already been counted would be great. Thank you
I'm not sure if I understand what you mean, but maybe changing the loops order would help?
for (int i = 0; i < cfg.size(); ++i)
{
for (int k = 0; k < terminal.size(); ++k)
{
for (int j = 0; j < cfg[i].size(); ++j)
{
if (strcmp(cfg[i][j].c_str(), terminal[k].c_str()) == 0)
{
++counter[k];
break;
}
}
}
}

Sudoku solving matrix, while statement gives an infinite loop

This code should produce a solved sudoku matrix, however the while statement puts it in an infinite loop. Removing the while statement gives me a matrix with some values still 99 or 0. And i can't generate 9 random numbers uniquely one by one.
IF YOU WANT TO RUN AND CHECK THE CODE, REMOVE THE WHILE STATEMENT.
int a[9][9];
int b[9][9];
int inputvalue(int x, int y, int value) //checks horizontally, vertically and 3*3matrix for conflicts
{
int i, j;
for (i = 0; i < 9; i++)
{
if (value == a[x][i] || value == a[i][y])
return 0;
}
for (i = (x / 3) * 3; i <= ((x / 3) * 3) + 2; i++)
{
for (j = (y / 3) * 3; j <= ((y / 3) * 3) + 2; j++)
if (b[i][j] == value)
return 0;
}
return value;
}
int main()
{
int i, j, k;
unsigned int s;
cout << "sudoku\n";
time_t t;
s = (unsigned) time(&t);
srand(s);
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
a[i][j] = 99;
}
for (i = 0; i < 9; i++)
{
for (j = 1; j <= 9; j++)//j is basically the value being given to cells in the matrix while k assigns the column no.
while(a[i][k]==99||a[i][k]==0)
{
k = rand() % 9;
a[i][k] = inputvalue(i, k, j);
}
}
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
return 0;
getch();
}
You are using assignment =, instead of equality == here:
while(a[i][k]=99||a[i][k]=0)
^ ^
this should be:
while(a[i][k]==99||a[i][k]==0)
a[i][k]=99 will always evaluate to true since 99 is non-zero, although your original code does not compile for me under gcc as it is, so I suspect the code you are running either has some parenthesizes or is slightly different.
Also using k in the while loop before it is initialized is undefined behavior and it is unclear that your termination logic makes sense for a k that is constantly changing for each loop iteration.
Another source of the infinite loop is inputvalue which seems to get stuck returning 0 in some instances, so you need to tweak that a bit to prevent infinite loops.
Also, srand(time(NULL)); is a more common way to initialize the pseudo-random number generator