Why I'm lossing data using realloc()? - c++

I'm still a beginner, so I don't know much and I'm sorry if it looks too dumb. I was learning about memory leak and how to use malloc(), calloc(), free() and realloc().
I tried this sample above on visual studio, however when I saw the results after using realloc, I didn't got the same values that was before on that struct.
#include <iostream>
#include <string>
struct sNum
{
int b = 0;
};
int main()
{
int n = 10;
struct sNum* a;
a =(struct sNum*) malloc(n * sizeof(struct sNum));
for (int i = 0; i < n; i++)
{
a[i].b = i;
std::cout << std::to_string(a[i].b) + " ";
}
std::cout << "\n";
n++;
a = (struct sNum*)realloc(a, n);
a[n - 1].b = n - 1;
for (int i = 0; i < n; i++)
{
std::cout << std::to_string(a[i].b) + " ";
}
return 0;
}
Running that code on visual studio, it results:
0 1 2 3 4 5 6 7 8 9
0 1 -50331646 -570556931 -572662307 -572662307 -757975909 -2147479587 -572662307 -572662307 10
I was expecting the same sequence, plus 10 at the end. Anyone knows what I'm doing wrong?
Thx in advance!

Assuming that sizeof(sNum) is 4 on your platform, the line
a =(struct sNum*) malloc(n * sizeof(struct sNum));
will allocate 40 bytes of memory.
The line
a = (struct sNum*)realloc(a, n);
will shrink the allocated memory to 11 bytes, which is only sufficient to store 2 elements.
Due to this, the line
a[n - 1].b = n - 1;
will invoke undefined behavior, because valid indexes into a are only 0 and 1 (because there is only room for 2 elements), however you are using the index 10.
Therefore, to fix this, you should change the line
a = (struct sNum*)realloc(a, n);
to:
a = (struct sNum*)realloc( a, n * sizeof(sNum) );

Related

Why don't my loop of incrementing pointer end but cut off and printing weird output?

I'm new to coding with pointers.
This is my code.
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int a = 1;
int* p = &a;
for (int i = 0;i < 10; i++) {
p++;
*(p) = rand() % 10 + 1;
cout << p << " " << *p << endl;
}
}
Somehow, the code keeps ending before the loop end and print out a series of address but then in the last address end with 03. Can anyone help I search all over but nothing.
output:
00000073532FF808 2
00000073532FF80C 8
00000073532FF810 5
00000073532FF814 1
00000073532FF818 10
00000073532FF81C 5
00000073532FF820 9
00000073532FF824 9
0000007300000003
First, there is allocated storage for one int.
int a = 1;
Second a pointer which points to this storage.
int *p = &a;
Now, writing to *p will modify a but...
for (int i = 0;i < 10; i++) {
p++;
*(p) = rand() % 10 + 1;
i.e. p is incremented.
Even in the first loop it now points to memory beyond a.
That memory is either allocated for something else, or used for something else, or not allocated at all.
In any case, this is Undefined Behavior i.e. writing out of bounds.
That's the nature of Undefined Behavior that everything is possible now—no predictions can be made anymore what will happen.
If the loop terminates before 10 iterations are done I suspect that i might be corrupted by this. It's also possible that p corrupts itself. This doesn't change the fact that it's Undefined Behavior.
A possible fix of OPs application would be to provide sufficient storage in a where p can be iterated over without going out-of-bounds.
For this, the definitions at the beginning of main() had to be changed to:
int a[11] = { 1 };
int* p = a; // could also be: int* p = &a[0];
Please, note that p is incremented before writing to it.
Hence, in the last iteration (with i = 9), p will point to a[10] before the write access. Therefore, the minimal sufficient array size is int a[11] instead of int a[10] which someone might think from the first glance.
The fixed program of OP:
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
int a[11] = { 1 };
int* p = a;
for (int i = 0;i < 10; i++) {
p++;
*(p) = rand() % 10 + 1;
cout << p << " " << *p << endl;
}
// double check
cout << "a:";
for (int value : a) cout << ' ' << value;
cout << endl;
}
Output:
0x7fff57151bc4 4
0x7fff57151bc8 7
0x7fff57151bcc 8
0x7fff57151bd0 6
0x7fff57151bd4 4
0x7fff57151bd8 6
0x7fff57151bdc 7
0x7fff57151be0 3
0x7fff57151be4 10
0x7fff57151be8 2
a: 1 4 7 8 6 4 6 7 3 10 2
Live Demo on coliru

Why are variable length arrays in C++ overlapping on some sizes?

After providing an answer to a question here, I was testing this code that I edited and noticed some strange behavior:
#include <iostream>
#define MAX 100
using namespace std;
int main()
{
int size = 0;
int array[MAX];
int i, j;
int input;
cout << "Array: ";
for(i = 0; i < MAX; i++)
{
cin >> input;
if(input == -1)
break;
else
{
array[i] = input;
size++;
}
}
cout << "Size: " << size << "\n\n";
int left[size / 2];
int right[size / 2];
for(i = 0; i < size / 2; i++)
left[i] = array[i];
for(i = size / 2, j = 0; i < size; i++, j++)
right[j] = array[i];
cout << "Left: ";
for(i = 0; i < size / 2; i++)
cout << left[i] << ' ';
cout << '\n';
cout << "Right: ";
for(i = 0; i < size - size / 2; i++)
cout << right[i] << ' ';
cout << '\n';
return 0;
}
This code is supposed to split the array into two separate arrays. Somehow the output is wrong when these are the input:
1 2 3 4 5 6 7 8 9 -1
Left: 9 2 3 4
Right: 5 6 7 8 9
After debugging If the elements of left were printed like this:
for(i = size / 2, j = 0; i < size; i++, j++)
{
right[j] = array[i];
cout << left[0] << ' ';
}
cout << '\n';
It says that the value of left[0] is modified after the 5th iteration:
1 1 1 1 9
Left: 9 2 3 4
Right: 5 6 7 8 9
This only happens when the array size is 9. I haven't tested beyond 16 yet. I could fix the code so that it would have the correct size
int right[size - size / 2];
or use malloc() to adhere to the C++ Standard,
int *left = (int *) malloc(sizeof(*left) * n / 2);
int *right = (int *) malloc(sizeof(*left) * n / 2);
so that left wouldn't be affected, but that's not what I'm asking. Why does it only happen when splitting an array size of 9? Why was left[0] overwritten? Is this is a bug in g++ that should be reported or is the problem something else?
It says that the value of left[0] is modified after the 5th iteration:
That is your answer. The problem occurs in the fifth iteration over an array with four elements.
When size is odd, the calculation of size/2 rounds down. So the sum size/2 + size/2 is strictly less than size, yet your loops ensure that all size elements from the original array are assigned somewhere. Something has to be assigned to an unexpected location. We call this "undefined behavior", and whatever the compiler does at that point is correct according to the C++ standard. (Whatever happens, the compiler gets to blame your code for it.) It just happens that when size is 9, the compiler used left[0] as the location for right[4].
Behind the scenes, the left and right arrays are probably more-or-less adjacent in memory. The layout would have right[0] through right[size/2], then possibly some unused space (also known as "padding"), then left[0] through left[size/2]. When you access one-past the last element of right, you end up either in the unused space or in left[0]. When you overwrite the unused space, you see no symptoms since that space is otherwise unused. However, when you overwrite left[0] you definitely see a symptom.
Your compiler apparently uses padding to make sure the arrays are aligned to 4*sizeof(int). (Must be faster that way, as compilers rarely introduce waste without a reason. Still, I am surprised it's not 2*sizeof(int) instead.) That is, there is no padding when size/2 is a multiple of 4. If this guesswork is accurate, you should see this behavior when size is odd and size/2 is a multiple of 4; that is when size is one more than a multiple of 8, as in 9, 17, 25, 33, etc.

Variable value stays through multiple test cases

My code takes in an array of positive and negative numbers. It then spits out what percentage of the array is Positive, negative, and zero. When my code runs through multiple test cases, some of the variables that I have initialized stay the same? Which is something i've never encountered before and I wonder if I am initiaizing them correctly. Here is my Code and a couple of test cases
void plusMinus(vector<int> arr) {
int len = sizeof(arr)/sizeof(arr[0]);
int pos = 0;
int neg = 0;
int zer = 0;
cout << len <<"\n";
double d = len;
double sum1 = 0;
double sum2 = 0;
double sum3 = 0;
for(int i =0; i<len; i++){
if(arr[i]>=1) {
pos++;
}
if(arr[i]<0) {
neg++;
}
if(arr[i]==0) {
zer++;
}
}
sum1 = pos/d;
cout << sum1 <<"\n";
sum2 = neg/d;
cout << sum2<<"\n";
sum3 = zer/d;
cout << sum3<<"\n";
}
an example of a test case that works is
6
-4 3 -9 0 4 1
an example of one that does not is
8
1 2 3 -1 -2 -3 0 0
int len = sizeof(arr)/sizeof(arr[0]);
This is typically used in normal arrays. Since you are using a vector, try instead to use:
int len = arr.size();
Why? sizeof yields the size in bytes of the object representation of the argument. For vectors, that's always 24 no matter how many elements. And sizeof for an element of that vector<int>, is just sizeof(int), which is usually 4 bytes. Badabing badaboom, sizeof(vector<int>)/sizeof(vector<int>[0]) is always 6.

Trash in operating memory with dynamic arrays

I've tried to make an algorithm, which counts how many numbers are divided without a remainder. Code works, but every time I run it, I'm getting "trash" numbers in my output. I'm using dynamic arrays to solve a problem.
#include <iostream>
using namespace std;
int main()
{
int N = 30;
int *data = new int [N];
for (int i = 0; i < 100; i++)
{
for (int c = 1; c < N; c++)
{
if (i % c == 0)
{
data[c] += 1;
}
}
}
for (int k = 1; k < N; k++)
{
cout << data[k] << endl;
}
delete [] data;
}
I've expected to have, at least, what C++ Shell says: http://cpp.sh/6xtc
100
50
34
25
20
17
15
13
12
10
10
9
8
8
7
7
6
6
6
5
5
5
5
5
4
4
4
4
4
, but got in different IDE the same result:
100
11932994
34
25
20
17
15
13
12
620757039
37045
11951945
8
11927896
7
7
7290
158
6
5
5
570425383
37040
11951941
4
11927892
4
1835102827
859059803
You do
int *data = new int [N];
And allocate an N-sized array. Then you immediately start trying to increment the values in it:
data[c] += 1;
But what was in there to begin with?
If you want to guarantee that all the values will be initialized to 0, per this answer you can allocate your array with:
int *data = new int [N]();
// ^^^^
<Obligatory "you should just be using std::vector!" comment here.\>
(But actually though, vectors would make this way easier and avoid this issue entirely)
data[c] += 1;
You add something to an uninitialized value. data[c] was not necessarily 0 before that. new does not initialize a dynamic array to zero.
Quit all new/delete and use std::vector<>. And, do learn to use the debugger - really helpful in this case.

Why can't I assign 1 element to 2> size dynamic tab?

Simplified version of my code looks like:
int * tab = nullptr;
int index = 0;
int size = 1; // Program works unless this is init'd to something higher!
int a = 0;
while (true)
{
int input;
std::cin >> input;
if (input == 0) break;
index++;
if (index >= size) {
size = size * 2;
int * newt = new int[size];
for (int i = 0; i < a; ++i)
newt[i] = tab[i];
delete[] tab;
tab = newt;
}
tab[a] = input;
a++;
}
Whenever I try to change 'size' integer to be bigger than 1, the program crushes. Visual Studio shouts about memory accessibility problem, but still I can't figure what's exactly wrong.
I don't have to change it, but I've struggled with this code for more than hour untill I accidently changed variable to be 1 and then it worked. I'm just curious why.
If size is bigger than one, then index >= size won't be true on the first iteration, none of the code that results in tab pointing to something is executed, so the tab[a] access is broken.
Your algorithm is rather hard to follow so I'm not proposing a concrete resolution, except to suggest redesigning it.
In addition to Lightness Races in Orbit:
Here, my approach for a revised version:
#include <iomanip>
#include <iostream>
#include <sstream>
int main()
{
int *tab = nullptr;
int len = 0, size = 0;
std::stringstream in;
in << "1 2 3 4 5 6 7 8 9 10 0";
while (true)
{
int input;
//std::cin >> input;
in >> input;
if (input == 0) break;
if (len >= size) {
size = std::max(2 * size, 1);
int * newt = new int[size];
for (int i = 0; i < len; ++i) newt[i] = tab[i];
delete[] tab;
tab = newt;
}
tab[len++] = input;
}
for (int i = 0; i < len; ++i) std::cout << ' ' << tab[i];
std::cout << '\n';
return 0;
}
Output:
1 2 3 4 5 6 7 8 9 10
Live Demo on coliru
I must admit that I still didn't get why the original version should be broken.
There is my try on coliru which seems to run fine (although I know – running fine doesn't mean there is no U.B.). Got it.