What I mean by "no simple way" is that there is no way that I can think of that would work for a reasonable situation[1]. There are ways, like you have mentioned, using _msize(), but that ONLY works for malloc-created memory blocks, nothing else, and it requires that you have the original memory allocation [at least the MSDN info doesn't say otherwise], so the following code wouldn't work:
Code:
void func(int *p, int index)
{
if (index >= _msize(p) / sizeof(int)) { exit with error };
... use p[index]
}
int main()
{
int *block;
block = malloc(sizeof(int) * 40);
func(&p[20], 10);
return 0;
}
Yes, malloc commonly allocates "a little bit extra", something like this would implement malloc and _msize, for example:
Code:
void *malloc(size_t size)
{
struct mdata *p;
size_t sz = size + sizeof(struct mdata);
p = low_level_allocation(sz);
p->size = size;
// perhaps other data to be filled in...
return (void*)&p[1];
}
size_t _msize(void *pp)
{
struct mdata *p = ((struct mdata *)pp)[-1]; // Not portable
return p->size;
}
[1]If you have access to OS-internal data, then you could potentially check if something would cause a memory violation, but just knowing that doesn't mean that it's correct to access the memory - for example, if we are in a call-stack with 15 calls, using an average of 100 bytes, this would be "valid memory access":
Code:
void func()
{
int a[5];
a[300] = 7;
}
It may well crash the system when some function about 12 levels below is returning, but it would not be detectable by checking if the memory is valid.
The only other way to solve this problem, which is how for example Pascal compilers often do range checking, is to pass the size of the data implicitly from one function to the next, and checking against the size for every access. But this is slow if it has to be done every function call and every access - and it relies on the compiler to pass sizes of arrays properly.
--
Mats