My program seems to always produce ridiculous errors.
Please provide directions for me. The following code segment cutout all irrelevant parts.
Thanks.
Part A of the code segment seems failed to initialize the array correctly, how to debug?
Part B of the code segment always crash, is there anything i missed?
typedef unsigned long T_PSIZE;
int main()
{
int AG_TOTAL = 6 ;
/* part A1 */
T_PSIZE* cntPeopleByAge = new T_PSIZE[AG_TOTAL + 1];
/* part A2 - originally i use static array like this, but it also fails */
//T_PSIZE cntPeopleByAge T_PSIZE[AG_TOTAL + 1];
for (int i = 0; i < (AG_TOTAL + 1); i++)
{
std::cout << i << ":" << cntPeopleByAge[i] << "\t";
cntPeopleByAge[i] = 0;
std::cout << cntPeopleByAge[i] << "\n";
}
std::cout << "cntPeopleByAge:" << cntPeopleByAge[ AG_TOTAL + 1 ] << "\n";
/* part B */
delete [] cntPeopleByAge;
return 0; // <--- crash here!
}
Sample Output
0:200320 0
1:201581 0
2:201582 0
3:201583 0
4:0 0
5:0 0
cntPeopleByAge:1799119387:0:0
Platform: win 7 x64
Compiler: TDM-GCC x64
for (int i = 0; i < (AG_TOTAL + 1); i++)
{
std::cout << i << ":" << cntPeopleByAge[i] << "\t";
// ^^^^^^^^^^^^^^^^
// You're reading uninitialized memory here
cntPeopleByAge[i] = 0;
std::cout << cntPeopleByAge[i] << "\n";
}
And here
std::cout << "cntPeopleByAge:" << cntPeopleByAge[ AG_TOTAL + 1 ] << "\n";
you're going out of bounds. The last valid index is AG_TOTAL.
You've got undefined behaviour (UB). The errors are only as ridiculous as UB can be.
/* Sorry. but that earlier answer is not correct. The loop correctly starts at zero and ends at < the limit. The problem is that you are declaring an array of pointers, but never allocating memory to the objects that they point to. Your output is showing you addresses not numbers. One way is to allocate the objects as you use them (you must delete them individually as well) */
T_PSIZE* cntPeopleByAge = new T_PSIZE[AG_TOTAL + 1];
for (int i = 0; i < (AG_TOTAL + 1); i++)
{
cntPeopleByAge[i] = new T_PSIZE();
}
What you really want to use is the vector class in the standard library which handles all of this for you:
#include <vector>
std:vector<T_PSIZE *> cntPeopleByAge;
cntPeopleByAgex.resize(AG_TOTAL + 1);
Good luck ...
Related
Here is the example:
#include <iostream>
#include <string>
#include <valarray>
int main()
{
std::valarray<std::string> vs(2);
// vs[0] += "hello"; // works
// vs[1] += "hello"; // works
vs += "hello"; // works
std::cout << vs[0] << std::endl;
std::cout << vs[1] << std::endl;
std::valarray<int*> vi(2);
vi[0] = new int[2];
vi[0][0] = 0;
vi[0][1] = 1;
vi[1] = new int[2];
vi[1][0] = 2;
vi[1][1] = 3;
std::cout << vi[0][0] << std::endl;
std::cout << vi[1][0] << std::endl;
// vi[0] += 1; // works
// vi[1] += 1; // works
vi += 1; // error: invalid operands of types 'int*' and 'int*' to binary 'operator+'
std::cout << vi[0][0] << std::endl;
std::cout << vi[1][0] << std::endl;
}
I don't understand this error, if someone may explain this to me.
Is there a workaround?
Best regards,
std::valarray doesn't have overloads for heterogeneous binary operations, but it does have a catch-all for other functions, apply.
vi.apply([](int * p){ return p + 1; });
You can see operator+ overloads for valarray here. As you can see no overload is suitable for what you're trying to do (add an int and a pointer).
My last dabble in C++ has been a while, so please excuse any slipups in terms of terminology/details.
What your error boils down to is that += on a valarray attempts to perform the operation on each element of the valarray. And by default (if my memory doesn't deceive me), there's no + operation for integer pointers, which are stored in your valarray. You'd need to specify an overridden + operator for int pointers first.
Also, for an explanation of why the other operations work and vi += 1 doesn't:
vi[0] += 1; // works
vi[1] += 1; // works
These work, because (and I don't know if that's what you intended to do) you've placed integers in these vararray fields (new int(n) will create an int with a value of n), each with a value of 2. So vi[0] is 2, as is vi[0]. You could as well have written
vi[0] = 2;
vi[1] = 2;
I'm assuming you were trying to instead have an integer array stored in vi[0]/vi[1], which would've been
vi[0] = new int[2];
vi[1] = new int[2];
The problem is that per documentation, vi[0][0] = 0, etc... simply prompt the valarray to create these fields if they don't exist already, so of course
std::cout << vi[0][0] << std::endl;
std::cout << vi[1][0] << std::endl;
will work.
I was testing some code for a class that wraps a 2-dimensional array of structs.
WrapperClass x;
SomeStruct try1 = x.at(0, 0);
SomeStruct try2 = x.at('a', 1);
SomeStruct array[] = {try1, try2};
// There were originally 3 of these test variables above, but I forgot to
// change the loop upper bound when I deleted one
for (int i = 0; i < 3; i++) {
// I added this line after noticing the non-error
std::cout << &array[i] << '\n';
std::cout << array[i].property1 << '\n';
std::cout << array[i].property2 << '\n';
std::cout << array[i].property3 << '\n';
std::cout << "-\n";
}
return 0;
This outputs:
0x7ffdadface08
0
0
0
-
0x7ffdadface14
0
0
0
-
0x7ffdadface20
0
0
0
Why doesn't this code segfault with an "access out of bounds" error or something? I only created 2 structs in the array; why is there suddenly a third one that I can freely and safely access?
Because it's undefined behavior and anything can happen, including no immediate error. I suggest you use containers such as vectors which are bounds-checked by good debug compilers.
I wrote a function within my code that should create some sort of matrices. It is fine when the size is small, but when it gets bigger, it crashes at the middle of this function without giving any information. I did that with both debug and release mode and same thing happened. Any idea on what can be wrong? Someone suggested me it could be buffer overrun.
In this function when kl.mechelms get bigger than a certain number, it crashes. The following code uses a function and gets a 3 by 3 matrix and stores it in kl.scoff which size is [3][3][kl.mechelms][kl.mechelms]. The problem happens when kl.mechelms are like bigger than 7000, but we need far more than that for our code.
Could the function Calc_3D which I use within this part cause the problem? I think it shouldn't since it just reads some values.
for (int z = 0;z<3;z++) {
for (int q = 0;q<3;q++) {
kl.scofsarr[z][q] = new double *[kl.mechelms];
}
}
for (int i = 0;i<kl.mechelms;i++) {
cout << "element " << i << "of " << kl.mechelms << endl;
kl.comments << "element " << i << "of " << kl.mechelms << endl;
for (int z = 0;z<3;z++) {
for (int q = 0;q<3;q++) {
kl.scofsarr[z][q][i] = new double[kl.mechelms];
}
}
for (int j = 0;j<kl.mechelms;j++) {
Calc_3D(i,j, kl.elmx[j], kl.elmy[j], kl.elmz[j], kl.anglemat[j], kl.dip[j], kl.elmx[i],kl.elmy[i],kl.elmz[i],
kl.elma[i],kl.rectza,kl.anglemat[i],kl.dip[i], kl.G, kl.v, kl.scofs, kl.rdepth);
for (int z = 0;z<3;z++) {
for (int q = 0;q<3;q++) {
kl.scofsarr[z][q][i][j] = kl.scofs[z][q];
}
}
}
}
I'm trying to understand why the following code behaves the way it does:
std::vector<int*> k;
for (int i = 0; i < 5; ++i) k.push_back(new int(i));
for (int i = 0; i < k.size(); ++i)
std::cout << "k[" << i << "]: " << *k[i] << "#" << k[i] << ", ";
std::cout << std::endl;
for (int i = 0; i < k.size(); ++i) {
int* p = k[i];
delete p;
if (i >= 2) {
k.erase(k.begin(), k.begin() + i);
k.push_back(new int(5));
break;
}
}
for (int i = 0; i < k.size(); ++i)
std::cout << "k[" << i << "]: " << *k[i] << "#" << k[i] << ", ";
std::cout << std::endl;
When I run this, the first time we print the contents of k I see this:
[0]: 0#0x1774e010, k[1] 1#0x1774e050, k[2]: 2#0x1774e030, k[3]: 3#0x1774e070, k[4]: 4#0x1774e0c0
This is what I expected. Then after the erase and the push i would expect the first two elements to be gone, the last three to be shifted, and the 5th one to appear at the end. However, i get this instead:
k[0]: 5#0x1774e030, k[1]: 3#0x1774e070, k[2]: 4#0x1774e0c0, k[5]: 5#0x1774e030,
I do see k[5] appearing at the end after the rest of the elements shifted but I am not understanding why it also appears as the first element too.
The second argument to vector::erase is a one past the end iterator. This is the typical form for iterator ranges in the standard C++ library.
So, when i == 2 the statement k.erase(k.begin(), k.begin() + i) only erases the first two elements, leaving the one you just deleted still in the vector. This goes on to cause bogus results when you try to use the deleted pointer.
(Technically it is undefined behaviour to do the erase also, since it involves reading the deleted pointer).
Possibly, the reason you see k[0]: 5#0x1774e030 instead of random garbage would be that your new int reallocates into the same space you just delete ; and I guess k[5]: on that line is a typo for k[3]: .
I'm trying to read pairs values from a file in the constructor of an object.
The file looks like this:
4
1 1
2 2
3 3
4 4
The first number is number of pairs to read.
In some of the lines the values seem to have been correctly written into the vector. In the next they are gone. I am totally confused
inline
BaseInterpolator::BaseInterpolator(std::string data_file_name)
{
std::ifstream in_file(data_file_name);
if (!in_file) {
std::cerr << "Can't open input file " << data_file_name << std::endl;
exit(EXIT_FAILURE);
}
size_t n;
in_file >> n;
xs_.reserve(n);
ys_.reserve(n);
size_t i = 0;
while(in_file >> xs_[i] >> ys_[i])
{
// this line prints correct values i.e. 1 1, 2 2, 3 3, 4 4
std::cout << xs_[i] << " " << ys_[i] << std::endl;
// this lines prints xs_.size() = 0
std::cout << "xs_.size() = " << xs_.size() << std::endl;
if(i + 1 < n)
i += 1;
else
break;
// this line prints 0 0, 0 0, 0 0
std::cout << xs_[i] << " " << ys_[i] << std::endl;
}
// this line prints correct values i.e. 4 4
std::cout << xs_[i] << " " << ys_[i] << std::endl;
// this lines prints xs_.size() = 0
std::cout << "xs_.size() = " << xs_.size() << std::endl;
}
The class is defined thus:
class BaseInterpolator
{
public:
~BaseInterpolator();
BaseInterpolator();
BaseInterpolator(std::vector<double> &xs, std::vector<double> &ys);
BaseInterpolator(std::string data_file_name);
virtual int interpolate(std::vector<double> &x, std::vector<double> &fx) = 0;
virtual int interpolate(std::string input_file_name,
std::string output_file_name) = 0;
protected:
std::vector<double> xs_;
std::vector<double> ys_;
};
You're experiencing undefined behaviour. It seems like it's half working, but that's twice as bad as not working at all.
The problem is this:
xs_.reserve(n);
ys_.reserve(n);
You are only reserving a size, not creating it.
Replace it by :
xs_.resize(n);
ys_.resize(n);
Now, xs[i] with i < n is actually valid.
If in doubt, use xs_.at(i) instead of xs_[i]. It performs an additional boundary check which saves you the trouble from debugging without knowing where to start.
You're using reserve(), which increases capacity (storage space), but does not increase the size of the vector (i.e. it does not add any objects into it). You should use resize() instead. This will take care of size() being 0.
You're printing the xs_[i] and ys_[i] after you increment i. It's natural those will be 0 (or perhaps a random value) - you haven't initialised them yet.
vector::reserve reserve space for further operation but don't change the size of the vector, you should use vector::resize.