问题
I just wonder that the compiler doesn't throw exception when I use non allocated space , here is a code for example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, n;
int *a;
printf("Number of elements to be entered:");
scanf("%d",&n);
a = (int*)calloc(n, sizeof(int));
printf("Enter %d numbers:\n",n);
for( i=0 ; i < n ; i++ )
{
scanf("%d",&a[i]);
}
printf("The numbers entered are: ");
for( i=0 ; i < n ; i++ )
{
printf("%d ",a[i]);
}
free( a );
return(0);
}
if n=3 for example and I statically said:
a[10]=3;
it will work and doesn't throw exception and I can print it, so what is the impact of using an element out of bound ? and is there a way to know the size ? because (sizeof) wont work on the calloc array.
回答1:
You have some dreaded undefined behavior (UB). Read Lattner's blog about What every C programmer should know about undefined behavior.
Notice that with UB, very bad things could happen, or nothing serious. And the observed behavior might not even be reproducible from one run to the next one (read about ASLR).
To explain what is happening on your system, you need to dive into implementation details, much lower than the C or C++ code. You could for example ask for the generated assembler (e.g. compile your code with gcc -Wall -O -fverbose-asm -S
and look into the generated *.s
assembler file). Or you could use (on Linux) something like strace(1) to understand the involved system calls.
I'm imagining that on Linux, the call to calloc
would ask the kernel for at least one page of heap data (i.e. calloc
would use mmap(2) or sbrk(2) ....) and since a page is 4Kbytes of data, the bytes you are accessing are in fact in your virtual address space.
BTW, I invite you to install and use some Linux distribution. Since it is mostly made of free software, you could study the involved source code (both your code, the standard C library, and the Linux kernel, perhaps even the compiler). That could take you many years, but you'll be able in principle to understand all the implementation details.
Read also Joel's law of leaky abstractions...
is there a way to know the size ? (of some heap-allocated data)
No, not in portable C. You should manage the size itself (i.e. have some way to know it). A useful trick might be to keep it near the array data, e.g. in a struct
containing the size, and ending with a flexible array member. But you still need some convention to get the size.
回答2:
Accessing data out of bounds gives you undefined behavior, which means anything can happen.
If you go far out of bounds, segmentation faults are to be expected due to accesses to unmapped or protected memory pages. However that assumes a somewhat straightforward mapping of your code to machine code.
The truth is, the compiler only gives you the illusion that your code maps straightforwardly to machine code. The moment you break the rules by causing undefined behavior, the illusion may break in some very bizarre ways and that's what undefined behavior is all about.
回答3:
Sorry, you cannot know the size of an allocated array (see: determine size of dynamically allocated memory in c)
whether accessing an out of bounds array will throw "exception" or not depends on the location of the array / the MMU boundaries. Anyhow, it's not to be relied upon!
To get "real" exceptions, switch to C++, drop the calloc
, use vector::at
.
来源:https://stackoverflow.com/questions/40194952/using-non-allocated-space-calloc