This causes a seg fault when I try to align the pointer returned by calloc to BY2PAGE. Is there a way (or is it even legal) to modify the pointer such that it is aligned after the allocation?
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define BY2PG 0x1000
char * vm;
static int roundup(u_int n, int align) {
if(n % align == 0) ;
// is already aligned so
// no action required, else
// align it:
else n = (align - (n % align));
return n;
}
int main() {
vm = (char *) calloc(0x100000, sizeof(char));
vm = (char *) roundup((u_int)vm, BY2PG);
vm[0] = 5; // seg fault
}
CodePudding user response:
Rather than risk implementation and undefined behavior with brittle user code, to align an allocation, use:
void *aligned_alloc(size_t alignment, size_t size);
The
aligned_alloc
function allocates space for an object whose alignment is specified by alignment, whose size is specified by size, ...
OP is assuming 1) (u_int)vm
does not lose vital information (I think this is the seg fault source) 2) that the adjusted integer, cast to an int
, converted back to a pointer is valid 3) calloc(large_value, 1)
returned non-NULL
@Lindydancer
.
Even the initial allocation is suspect as calloc(0x100000, sizeof(char));
it is unclear how many 0x1000
sized blocks are available to use after the questionable roundup()
.
CodePudding user response:
Thanks to @WeatherVane - this version works as I expected
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define BY2PG 0x1000
char * vm;
static uintptr_t roundup(uintptr_t n, int align) {
if(n % align == 0) ;
// is already aligned so
// no action required, else
// align it:
else n = (align - (n % align));
return n;
}
int main() {
vm = (char *) calloc(0x100000, sizeof(char));
printf("x\n", vm);
vm = (char *) roundup((uintptr_t)vm, BY2PG);
printf("x\n", vm);
vm[0] = 5;
printf("%d\n", vm[0]);
}