[petsc-dev] Allocating arrays
Jed Brown
jedbrown at mcs.anl.gov
Sat Nov 30 12:50:59 CST 2013
I'm tired of mistakes matching types when allocating memory.
PetscMPIInt *array;
PetscMalloc(n*sizeof(PetscInt),&array);
This is not caught in debug mode due to:
#if defined(PETSC_USE_DEBUG)
#define PetscMalloc2(m1,t1,r1,m2,t2,r2) (PetscMalloc((m1)*sizeof(t1),r1) || PetscMalloc((m2)*sizeof(t2),r2))
#else
#define PetscMalloc2(m1,t1,r1,m2,t2,r2) ((*(r2) = 0,PetscMalloc((m1)*sizeof(t1)+(m2)*sizeof(t2)+(PETSC_MEMALIGN-1),r1)) || (*(r2) = (t2*)PetscAddrAlign(*(r1)+m1),0))
#endif
At least it generates a warning when compiling optimized mode with
64-bit ints. A similar problem arises when confusing PetscReal for
PetscScalar.
But this can be much simpler:
#define PetscMallocA(n,p) (PetscMalloc((n)*sizeof(**(p)),(p)))
Now it is always correct to write
PetscMallocA(n,&array);
To break up the common sequence of PetscMalloc followed by PetscMemzero,
I would add
#define PetscCalloc(n,p) (PetscMalloc((n),(p)) || PetscMemzero(*(p),(n))) /* Could use calloc() if we add support */
#define PetscCallocA(n,p) (PetscCalloc((n)*sizeof(**(p)),(p)))
And we can extend to more cases, e.g.,
#if defined(PETSC_USE_DEBUG)
# define PetscMallocA2(n0,p0,n1,p1) (PetscMallocA((n0),(p0)) || PetscMallocA((n1),(p1)))
#else
# define PetscMallocA2(n0,p0,n1,p1) (PetscMalloc((n0)*sizeof(**(p0))+(n1)*sizeof(**(p1))+(PETSC_MEMALIGN-1),(p0)) || (*(void**)(p1) = PetscAddrAlign(*(p0)+(n0)),0))
#endif
This is used like
PetscMallocA2(n0,&array0,n1,&array1);
I've used similar macros in non-PETSc projects for years and I find it's
a lot cleaner, less error-prone, and easier to change types. Is anyone
opposed to me adding PetscMallocA* functions?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: <http://lists.mcs.anl.gov/pipermail/petsc-dev/attachments/20131130/994b5387/attachment.sig>
More information about the petsc-dev
mailing list