This question already has an answer here:
-
Crash or “segmentation fault” when data is copied/scanned/read to an uninitialized pointer
3 answers
Can't you just store as much data as you want using pointer?
Why do you have to use malloc()
to gain more memory?
int * a;
int max, i;
printf("Enter the maximum number you want: ");
scanf("%d", &max);
for (i = 0; i < max; i++)
{
* (a + i) = i;
}
for (i = 0; i < max; i++)
{
printf("%d\n", * (a + i));
}
return 0;
so I let the user choose whatever number, and computer will 'allocate the memory' right? instead of using the following code:
a = (int *) malloc(10 * sizeof(int));
In your code,
* (a + i) = i;
is wrong, because you're trying to write into uninitialized memory. This in turn invokes undefined behaviour.
To elaborate, just defining a pointer does not automatically allocate limitless accessible memory to that pointer. You need to add the location where the pointer will be pointing to. When you simply define a pointer (local), it points to some unknown memory location which is most likely neither valid nor accessible by your program. So, when you try to access that memory location, it is essentially accessing some invalid memory. This is UB.
So,
Why do you have to use malloc to gain more memory?
malloc()
is not used to gain more memory, rather it is giving the required memory location to be accessed.
EDIT:
Regarding your edit,
a = (int *) malloc(10 * sizeof(int));
two things to add,
- Please see why not to cast the return value of
malloc()
and family in C
.
- Always check for the success of
malloc()
before using the returned pointer.
A pointer has to point to some location in memory, so never write
int* x;
*x=...;
But write
int* x=expression that results in an valid address;
First consider a simple computer without MMU and a fancy multitasking OS. Then you can use any address, but you have to know you do not replace your code, and any important data. You will benefit from having a reserved space for code, the call stack and perhaps other data. Some machines connects addresses to peripherals, so writing there would make some physical stuff happen. This is called memory mapped I/O. To know what you are doing, you create your address layout, which on a 16 bit machine may look like
+------------------+ 0x0000
| Memory mapped IO |
+------------------+ 0x0100
| Program |
| |
+------------------+ 0x4000
| Call stack |
| (local variables)|
+------------------+ 0x8000
| Other data |
| globals |
| heap |
+------------------+ 0xffff
This fictive machine has 255 I/O ports (0x0000 is reserved), and will start program on address 0x0100. The remaining part of the address layout is up to you. Here 16128 bytes is reserved for the program , 16384 bytes for the stack and 32767 bytes left for other data. If you know that your program never becomes larger than 8 kB, then feel free to increase your call stack or heap. A program that sets the rotation speed of a motor may look like
int main()
{
const uint8_t* speed_regulator=(const uint8_t*)0x0001; //Port for speed controller is 0x0000
uint8_t* motor_voltage=(uint8_t*)0x0002; //Port for motor controller
while(true)
{
*motor_voltage=*speed_regulator;
}
}
Some care must be taken here, so the compiler does not optimise out the loop, which is our data pump.
Now you want a multitasking system with virtual memory and all modern stuff. But then you cannot use arbitrary addresses any more. To make it possible to give you a valid address, and to inform the OS about how much memory you need, the function malloc
exists.
so I let the user choose whatever number, and computer will 'allocate the memory' right?
Some languages work like that; the runtime environment will allocate memory from the heap (or whatever memory pool) as necessary.
C does not work that way. When you declare
int *a;
a
doesn't initially point anywhere meaningful; if declared static
or at file scope it initially contains NULL
, and if declared within a block it contains an indeterminate value which may or may not point to a writable memory location. It does not automatically point to the heap, and writing *(a + i) = i
(or a[i] = i
, which is the same thing) won't automatically allocate any new memory.
C puts all the burden on the programmer for managing dynamically allocated memory. If you need additional memory at runtime, you must use malloc
or realloc
, and when you're done with that memory, you must deallocate it using free
.