So I've got code:
float **array = new float*[width + 1]; //old line was '= new float*[width]'
//Create dynamic 2D array
for (int i = 0; i < width; ++i) {
array[i] = new float[height + 1]; //old line was '= new float[height]'
}
//Hardcode 2D array for testing
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
array[i][j] = i + j;
}
}
//deallocate heap memory
for (int i = 0; i < width; ++i) {
delete [] array[i]; //Where corrupted memory error used to be
}
delete [] array;
(For the record, I know it would be more efficient to allocate a single block of memory, but I work closely with scientists who would never understand why/how to use it. Since it's run on servers, the bosses say this is preferred.)
My question is why does the height+1/width+1 fix the corrupted memory issue? I know the extra space is for the null terminator, but why is it necessary? And why did it work when height and width were the same, but break when they were different?
SOLN:
I had my height/width backwards while filling my array... -.-; Thank you to NPE.
The following comment is a red herring:
delete [] array[i]; //Where corrupted memory error used to be
This isn't where the memory error occurred. This is where it got detected (by the C++ runtime). Note that the runtime isn't obliged to detect this sort of errors, so in a way it's doing you a favour. :-)
You have a buffer overrun (probably an off-by-one error in a loop) in the part of your code that you're not showing.
If you can't find it by examining the code, try Valgrind or -fsanitize=address in GCC.
edit: The issue with the code that you've added to the question:
//Hardcode 2D array for testing
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
array[i][j] = i + j;
}
}
is that it has width and height (or, equivalently, i and j) the wrong way round. Unless width == height, your code has undefined behaviour.
Changing height and weight by height+1 and weight+1 is probably not going to be enough.
The code you posted was correct with height and weight.
This means that something was likely writing just past the end of those arrays in some other part of the code, and when you grew those arrays, it made the faulty code write right at the end of the arrays instead of crashing. You didn't fix the issue, you just hid it.
The code actually crashed on the delete[] due to some limitations in how the OS detects heap corruptions. Very often off-by-one errors on the heap will be detected by the next call to new/delete/malloc/free, not when they actually happen.
You can use tools like Valgrind if you want to know exactly when and where your program does illegal things with pointers.
You didn't fix the code. What you are doing is changing the executable with the new code, thus moving the corruption bug to another part of your program.
One thing you should not do -- do not change your program to the one you say "works" with the + 1 and then accept it. I know it may be tempting if the bug is hard to diagnose, but don't go this route.
What you must do is go back to the non-working version, and really fix the issue. By "fix", meaning you can explain what the fix does, why it fixes the problem, etc.
Related
I'm writing a code which calculates the inverse matrix given a matrix, the thing is, I need that to be included in other code that makes statistical fits, so I need something like a function that receives the size of the matrix (matrix is square matrix) and the matrix itself and returns his inverse, I found something about the syntax and then have this (Gauss-Jordan)
float* inv(int n, float *A)
{
float* I = 0;//*
float aux;
float pivote;
for(int i = 0; i<n; i++){
for(int j = 0; j<n; j++){
if(i == j)
{
*(I+i*n+j) = 1.0; //*
}
else {
*(I+i*n+j) = 0.0;
}
}
}
for(int i = 0; i<n; i++)
{
pivote = *(A+i*n+i);
for(int k = 0; k<n; k++)
{
*(A+i*n+k) = *(A+i*n+k)/pivote;//*
*(I+i*n+k) = *(I+i*n+k)/pivote;//*
}
for(int j = 0; j<n; j++)
{
if(i!=j)
{
aux = *(A+j*n+i);//*
for(int k = 0; k<n;k++)
{
*(A+j*n+k)=*(A+j*n+k)-aux**(A+i*n+k);//*
*(I+j*n+k)=*(I+j*n+k)-aux**(I+i*n+k);//*
}
}
}
}
return I;//*
}
There where I put the //* is where I have my doubts, is the syntax correct? the declarations, there in the return should be something else than just I?. When I compile I get a segmentation fault, Following Taekahn recommendations, compiling with sanitizers g++ -fsanitize=address -fsanitize=undefined -fsanitize=leak inverse.cpp I get
inverse.cpp:148:28: runtime error: store to null pointer of type 'float'
AddressSanitizer:DEADLYSIGNAL
=================================================================
==11993==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x00000040338c bp 0x7ffdd6a14510 sp 0x7ffdd6a144b0 T0)
==11993==The signal is caused by a WRITE memory access.
==11993==Hint: address points to the zero page.
#0 0x40338b in inv(int, float*) (/home/live/med_elect/a.out+0x40338b)
#1 0x402f30 in main (/home/live/med_elect/a.out+0x402f30)
#2 0x7f90ffed9e5a in __libc_start_main (/lib64/libc.so.6+0x23e5a)
#3 0x402289 in _start (/home/live/med_elect/a.out+0x402289)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/live/med_elect/a.out+0x40338b) in inv(int, float*)
==11993==ABORTING
I really appreciate if you can help me, thank you very much in advance and thank you very much for the feedback in the comments, I'm new here with the questions.
UPDATE: Thanks to nasy for the answer, It is important to note that many people mentioned the vector approach, so, to anyone reading this, check the comments and better try the vector approach.
In your second function, you have float *I = 0. Later on, you try to write to this array but you have not allocated it. The way you're indexing your matrices is the flattening approach so you must write float *I = new float[n*n]. There are different approaches, of course, like using dynamic 2D arrays, 2D vectors, etc. as mentioned in the comments.
The problem is that the pointer I doesn't point to any object and you've the following statement:
*(I+i*n+j) = 1.0; //undefined behavior
The above statement leads to undefined behavior. Imagine what happens when i and j are both 0 in the first iteration. Then you're dereferencing I which doesn't point to any float object and thus this is undefined behavior.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash which happens in your case.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
Also, it would be better to use std::vector than doing manual memory management using new and delete.
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.
As stated above my program works in Debug and Release without debug (ctrl + F5) however does not work in simply Release.
Just to clarify I have already checked to see if I have some uninitialized variables and I haven't (to the best of my knowledge anyway but I have spent quite some time looking).
I believe to have localized the issue and what I have come across is, in my opinion, very bizarre. First I set up the break points as shown in the picture below:
Then I run the program in release. And instantly the top break point moves:
I found this extremely odd. Now note the number 6302 assigned to 'n'. This number is correct and what I hoped to pass through. Now watch as I continue through the program.
We are still in good shape but then it turns for the worst.
'n' changes to 1178521344, which messes up the rest of my code.
Would someone be able to shed some light on the situation, and even better, offer a solution.
Thanks,
Kevin
Here is the rest of the function if it helps:
NofArr = n;
const int NA = n;
const int NAless = n-1;
double k_0 = (2*PI) / wavelength;
double *E = new double[NAless]; // array to hold the off-diagonal entries
double *D = new double[NA]; // array to hold the diagonal entries on input and eigenvalues on output
int sizeofeach = 0;
trisolver Eigen;
int* start; int* end;
vector< vector<complex <double>> > thebreakup = BreakUp(refidx, posandwidth, start, end);
for(int j = 0; j < (int)thebreakup.size(); j++){
// load the diagonal entries to D
for(int i =0; i < (int)thebreakup[j].size(); i++){
D[i] = -((double)2.0/(dx*dx)) + (k_0*k_0*thebreakup[j][i].real()*thebreakup[j][i].real());
}
// load the off diagonal
for(int i = 0; i < (int)thebreakup[j].size(); i++){
E[i] = (double)1.0 / (dx*dx);
}
sizeofeach = (int)thebreakup[j].size();
double *arr1= new double[sizeofeach];
arr1 = Eigen.EigenSolve(E, D, sizeofeach, mode);
complex <double> tmp( PhaseAndAmp[j][1]*cos(PhaseAndAmp[j][0]), PhaseAndAmp[j][1]*sin(PhaseAndAmp[j][0]));
// rebuild the break up with the mode
for(int i = 0; i < (int)thebreakup[j].size(); i++){
thebreakup[j][i] = (complex<double>(arr1[i],0.0)) * tmp ;
}
delete []arr1;
}
vector<complex<double>> sol = rebuild(thebreakup, start, end);
delete [] E;
delete [] D;
delete [] start;
delete [] end;
return sol;
I'm writing this as an answer, because it's way harder to write as a comment.
What strikes me immediately is the array "arr1"
First you allocate new memory and store a pointer to it in the variable arr1
double *arr1= new double[sizeofeach];
Then, immediately, you overwrite the address.
arr1 = Eigen.EigenSolve(E, D, sizeofeach, mode);
Later, you delete something. Is it safe?
delete []arr1;
It's not the double array you allocated, but something eigensolve returned. Are you sure you have the right to delete it? Try removing the delete here. Also, fix the memory leak too, by removing allocation in the first line I gave.
What worries me even more is that the "this" pointer changes. There is some nasty problem somewhere. At this point, your program has already been corrupted. Look for the issue somewhere else. Valgrind would be a GREAT tool if you can try to compile under linux.
It seems that there is some sort of code optimization going on in your program. It is not always easy to debug optimized code step-by-step since the optimization may reorder instructions.
I cannot see why the fact that 'n' changes to an apparently uninitialized value would be the root cause of the problem, since 'n' is anyways no longer used in your function. Seems like the memory is simply been released as part of the optimization.
I have discovered my mistake. Earlier in the program I was comparing pointers, not what they were pointing at. A stupid mistake but one I wouldn't have spotted without a long debugging session. My boss explained that the information given at the bottom of Visual Studio whilst in release mode cannot be trusted. So to "debug" I had to use std::cout and check variables that way.
So here is the mistake in the code:
if(start > end){
int tmp = start[i];
start[i] = end[i];
end[i] = tmp;
}
Where start and end were defined earlier as:
int* start = new int[NofStacks];
int* end = new int[NofStacks];
And initialized.
Thanks to all those who helped and I feel I must apologise for the stupid error.
The Fix being:
if(start[i] > end[i]){
int tmp = start[i];
start[i] = end[i];
end[i] = tmp;
}
I've written a program that works for most input, but if I ask it to make a increase precision by using a larger array (about 320x320 was when I started seeing trouble) it crashes. I searched for my issue online and found this similar problem and this tutorial on what to do about it. The problematic part of my original code is below - I had precision=320 and holepop=770.
double spacing = 2.0/(precision+1);
int lattice_int[precision][precision];
for (i=0; i<precision; ++i){
for (ii=0; ii<precision; ++ii){
mindist_sq = 2.0;
lattice_int[i][ii] = 0;
for (iii=0; iii<holepop; ++iii){
xdist = abs(xcoord[iii] + 1.0 - spacing/2 - spacing*i);
ydist = abs(ycoord[iii] - 1.0 + spacing/2 + spacing*ii);
thisdist_sq = xdist*xdist+ydist*ydist;
if (thisdist_sq < mindist_sq){
lattice_int[i][ii] = dint[iii];
mindist_sq = thisdist_sq;
}
}
}
}
I tried to fix it with this change in the first two lines:
int * lattice_int;
double spacing = 2.0/(precision+1);
lattice_int = new int[precision][precision];
(I also put in "delete lattice_int[][];" at the end.) However, I received this error: 'precision' cannot occur in a constant expression
Is it because I'm trying to work with multiple indices? What can I do to work around my problem? Thank you!
Don't use new[], it'll only cause you pain, suffering, memory leaks, use-after-frees, etc.
You can use std::vector in this respect.
std::vector<std::vector<int>> lattice_int(precision, std::vector<int>(precision));
No memory freeing necessary.
Your lattice_int variable is 2d array. You can allocate it using following code:
int precision = 500;
int ** lattice_int;
double spacing = 2.0/(precision+1);
lattice_int = new int*[precision];
for (int i = 0; i < precision; i++)
{
lattice_int[i] = new int[precision];
}
Same way you have to iterate for deletion of each sub array.
Note: This is pure illustration to use pointers for creating two dimensional array. The better way would be to use vector for this.
I've a segfault that I don't understand.
It always occurs at i = 0 and j between 1000 and 1100.
Here is the backtrace and all the sources required to see the problem: https://gist.github.com/Quent42340/7592902
Please help me.
EDIT: Oh I forgot. On my gist map.cpp:72 is commented. It's commented in my source code too. I did that to see where the problem came from, but even without that line, the problem is still here.
I see you allocate an array of pointers here:
m_data = new u16*[m_layers];
But, I never see you allocate the second dimension to this array. It seems like you ought to allocate the rows of your map, either as one large chunk of memory that you separate into chunks yourself, or new each row.
For example, if you add one line to your for (i ...) loop:
for(u8 i = 0 ; i < m_layers ; i++) {
m_data[i] = new u16[m_width * m_height];
If you go that route, you'll also need to upgrade your destructor:
Map::~Map() {
// WARNING: This doesn't handle the case where the map failed to load...
// Exercise for the reader.
for (u8 i = 0; i < m_layers; i++) {
delete[] m_data[i];
}
delete[] m_data;
}
An alternate approach would be to use std::array and let the C++ standard library manage that for you.
I'm using C++ to use vtk and when I hardcode vertices, my program works fine. However, when I try to implement a for loop (to hold x-many vertices), the whole program crashes.
Here's the code I'm working with:
vtkIdType totalVertex[9];
for(int i = 0; i < sizeof(totalVertex); i++){
totalVertex[i] = g->AddVertex();
}
// Hardcode example for syntax:
// vtkIdType v1 = g->AddVertex();
This would get 9 vertices and then I could manipulate them with commands such as
g->AddEdge (totalVertex[0], totalVertex[1]);
But my code never makes it to the place where edges are added, instead deciding to break in the loop. I'm new to C++ so any ideas would be nice.
This may not solve your issue, but there's a problem with
for(int i = 0; i < sizeof(totalVertex); i++)
and it may be related to the issue you're having.
sizeof in C++ yields size of whatever you provide in bytes, not the length of an array. Unless vtkIdType is one byte wide, you'll have errors. The "old-fahioned C way" to do this correctly would be
for(int i = 0; i < sizeof(totalVertex) / sizeof(totalVertex[0]); i++)
A cleaner, more modern C++ way would be
#include <array>
std::array<vtkIdType, 9> totalVertex;
for(int i = 0; i < totalVertex.size(); i++){
totalVertex[i] = g->AddVertex();
}