why leads pointer cast from double*** to double** to a write access violation?

132 views Asked by At

I have to integrate the code from tetgen (mesh generator), which is obviously used quite often. However, I have to use the old version (1.4.3 instead of 1.5) and this gives me a 'write access violation'. The relevant function is here:

void tetgenmesh::dummyinit(int tetwords, int shwords)
{
  unsigned long alignptr;

  // Set up 'dummytet', the 'tetrahedron' that occupies "outer space".
  dummytetbase = (tetrahedron *) new char[tetwords * sizeof(tetrahedron)
                                          + tetrahedrons->alignbytes];
  // Align 'dummytet' on a 'tetrahedrons->alignbytes'-byte boundary.
  alignptr = (unsigned long) dummytetbase;
  dummytet = (tetrahedron *)
    (alignptr + (unsigned long) tetrahedrons->alignbytes
     - (alignptr % (unsigned long) tetrahedrons->alignbytes));
  // Initialize the four adjoining tetrahedra to be "outer space". These
  //   will eventually be changed by various bonding operations, but their
  //   values don't really matter, as long as they can legally be
  //   dereferenced.
  dummytet[0] = (tetrahedron) dummytet;
  dummytet[1] = (tetrahedron) dummytet;
  dummytet[2] = (tetrahedron) dummytet;
  dummytet[3] = (tetrahedron) dummytet;
...
...
...
}

'dummytetbase' and 'dummytet' are both double*** pointers, tetrahedron is a double** pointer.

Example values are:

'tetwords' is : 12.

'(unsigned long)tetrahedrons->alignbytes' : 8.

'tetwords*sizeof( tetrahedron ) + tetrahedrons->alignbytes' is : 104.

'(alignptr % (unsigned long)tetrahedrons->alignbytes)' is : 0.

The code compiles fine, but when the pointer cast from 'dummytet' to 'dummytet[0]' should be done, I get this 'write access violation'.

So, dummytet gets the adress of dummytetbase + 8. And also dummytet[x] get all the same adress, but this leads to the write violation.

Any idea why this happens? Thanks!

1

There are 1 answers

6
MSalters On

Simple: double*** and double** are totally different types. double*** points to a double** while double** points to a double*. Apply this logic recursively.

Now since both are pointers, the compiler will use 32 or 64 bits for both. You can tell the compiler to shut up, cast the difference away, and ignore this problem at compile time. That means your compile-time problem now has run-time symptoms.

Take a step back: If you have a T* ptr and need a T value, you don't write (T) ptr. You write *ptr, or ptr[5], or something like that. This still holds when T==double**.