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?
pgp6LccUe8hOy.pgp
Description: PGP signature
