Iterate a Dynamically Allocated Array - c

I need to dynamically allocate an array of type int with size 12MB. I did it as follows:
unsigned int *memory;
memory = (int *) malloc( 3072 * sizeof(int));
How would I iterate through the array without having to use 3072? Is there a way to get the length of the array? Or should I just do for (int i = 0; i < 3072; i++)?
Thanks

The is no portable or convenient way to find out how large the allocate chunk is. After malloc is done all that is visible is a pointer to an indeterminate amount of memory (*). You must do the bookkeeping yourself.
(*) Actually malloc and friends do know how large the chunk is but there is no standard way for a client to access this information.

Pointers in C have no inherent length hence there is no way to do this. You must keep the length paired with the pointer throughout it's lifetime.

There is no other way. You should put 3072 in a const int, which would make the code better and more maintainable.

With MSVC and MinGW you can use the nonportable _msize function, like
char *c=malloc(1234);
printf("%lu",(unsigned long)_msize(c));
free(c);

Related

Create an array based on the input size

I am pretty new to C and I am trying to read the user input (some sentence or string in general) and then I want to create an array based on the input lenght. Is there a reasonable way to do it? Thanks for answers
Just for an overview of why all the answers are suggesting pointers instead of arrays:
When I was learning C one thing that helped was to understand arrays and pointers and how similar they are.
For the most part, they can have the same syntax, you can use * syntax with either or you can use [] syntax with either.
The differences are:
1) Arrays have memory allocated for them by the system and pointers don't, you have to "set" a pointer to some memory that you have allocated.
2) I don't think arrays can change where arrays point, they always point at their pre-allocated spot.
Since arrays are pre-allocated and can't be repointed, you want a pointer. You can treat it exactly as an array (You can use [] syntax) but you have to allocate memory for it first.
So for example, if a array with and p is a pointer, a[0]=1, *a=1, p[0]=1 and *p=1 are all identical functions, and while *++p=1 is valid, I don't think *++a=1 is valid because you can't change where a points.
So the short version would be, you need a pointer, not an array, and to change how much is allocated, you allocate the new size (With malloc or something similar), copy what you want to retain over and free the old space (Or you might be able to increase the size of the first one--realloc?, not sure, my C is decades old)
malloc/free, in the case of strings a strlen will get you it's length.
You can use malloc to allocate new memory, Note that since C's memory isn't managed (contrary to Java, Python or any other high level language), you will have to free the memory once you are done using it.
int arr_size = 0;
int* arr;
printf("Please enter a size to the array:");
scanf("%d", &arr_size);
arr = malloc(arr_size * sizeof(int))
// Use array
free(arr);
void *malloc(size_t size);
The malloc() function allocates size bytes and returns a pointer to
the allocated memory. The memory is not initialized. If size is 0,
then malloc() returns either NULL, or a unique pointer value that can
later be successfully passed to free().
It depends on the standard you're compiling against and your compiler. You can only rely on variable length arrays in C99
The only way to be certain is to use malloc, though you need to ensure you free the memory afterwards:
int length;
// Do something to set the size
// Allocates a contiguous block of memory that is
// (length * size of a char primitive) in length
char *array = (char *)malloc(length * sizeof(char));
// Do whatever you need do to with the array
free(array);
In C, declaring a variable as a pointer (char *a) and as an array (char a[3]) allows you to use that variable in exactly the same way. The only difference is that with a pointer you need to allocate and free the memory yourself, while with the array that block of memory is given to you automatically and it is freed when it goes out of scope.
With the code above, you can still access each individual character via an index like so:
array[0] = 'f';
array[1] = 'o';
array[3] = 'o';

why use malloc function in c when we can declare arrays using arr[size] ,taking input from the user for size?

why use malloc function when we can write the code in c like this :
int size;
printf("please the size of the array\n");
scanf("%d",&size);
int arr[size];
this eliminates the possibility of assigning garbage value to array size and is also taking the size of the array at run time ...
so why use dynamic memory allocation at all when it can be done like this ?
This notation
int arr[size];
means VLA - Variable-Length Array.
Standard way they are implemented is that they are allocated on stack.
What is wrong with it?
Stack is usually relatively small - on my linux box it is only 8MB.
So if you try to run following code
#include <stdio.h>
const int MAX_BUF=10000000;
int main()
{
char buf[MAX_BUF];
int idx;
for( idx = 0 ; idx < MAX_BUF ; idx++ )
buf[idx]=10;
}
it will end up with seg fault.
TL;DR version
PRO:
VLA are OK for small allocations. You don't have to worry about freeing memory when leaving scope.
AGAINST:
They are unsafe for big allocations. You can't tell what is safe size to allocate (say recursion).
Besides the fact that VLA may encounter problems when their size is too large, there is a much more important thing with these: scope.
A VLA is allocated when the declaration is encountered and deallocated when the scope (the { ... }) is left. This has advantages (no function call needed for both operations) and disadvantages (you can't return it from a function or allocate several objects).
malloc allocates dynamically, so the memory chunk persists after return from the function you happen to be in, you can allocated with malloc several times (e.g in a for loop) and you determine exactly when you deallocate (by a call to free).
Why to not use the following:
int size;
printf("please the size of the array\n");
scanf("%d",&size);
int arr[size];
Insufficient memory. int arr[size]; may exceed resources and this goes undetected. #Weather Vane Code can detect failure with a NULL check using *alloc().
int *arr = malloc(sizeof *arr * size);
if (arr == NULL && size > 0) Handle_OutOfMemory();
int arr[size]; does not allow for an array size of 0. malloc(sizeof *arr * 0); is not a major problem. It may return NULL or a pointer on success, yet that can easily be handled.
Note: For array sizes, type size_t is best which is some unsigned integer type - neither too narrow, nor too wide. int arr[size]; is UB if size < 0. It is also a problem with malloc(sizeof *arr * size). An unqualified size is not a good idea with variable length array (VLA) nor *alloc().
VLAs, required since C99 are only optionally supported in a compliant C11 compiler.
What you write is indeed a possibility nowadays, but if you do that with g++ it will issue warnings (which is generally a bad thing).
Other thing is your arr[size] is stored at stack, while malloc stores data at heap giving you much more space.
With that is connected probably the main issue and that is, you can actually change size of your malloc'd arrays with realloc or free and another malloc. Your array is there for the whole stay and you cannot even free it at some point to save space.

Questions about dynamic memory allocation in C

What is the difference between
int size;
int *arr;
scanf("%i", &size);
arr = malloc(size * sizeof(*arr));
and
int size;
scanf("%i", &size);
int arr[size];
When I want to allocate memory for 2 big numbers i would use the
following code:
unsigned long *big_nums;
big_nums = malloc(2 * sizeof(*big_nums));
I would access the first big bumber using big_nums[0] an the seond
one with big_nums[1]. Let's say unsigned long is 4 bytes big,
then the code would allocate 2 * 4 = 8 bytes. Let's say I do
something like this:
unsigned long *big_nums;
big_nums = malloc(7);
Using big_nums[0] is clear for me, but how about big_nums[1]? Will
it cause some kind of segmentation fault error or what?
There are two places to get memory from: the stack and the heap. The stack is where you allocate short lived things, and the heap is for allocating long term things.
malloc() allocates from the heap, and int arr[size] allocates from the stack.
When your function exits, arr[size] will be disposed of automatically, but malloc() will not. This leads to what's called "memory leaks".
big_nums = malloc(7);
will indeed be an error if you access big_nums[1]. In general the standard says behavior is "undefined" which means it could work, or might not.
For Q#1: The second version will (try to) allocate a variable-length array on the stack. In C99 onwards, this is possible; but in traditional C variable-length arrays don't exist, and you must roll them yourself using malloc.
For Q#2: You will be allowed to make that error. And when you write to the second element of the array, you will overwrite one byte that does not "belong" to you.
My guess is that in most cases, nothing bad will happen because malloc(7) will secretly be equivalent to malloc(8). But there is NO GUARANTEE of this. Anything could happen, including a segfault or something worse.
By the way, if you have two separate questions, it would be best to write them up as two separate questions. You get more points way.

how to calculate size of pointer pointed memory?

In one function I have written:
char *ab;
ab=malloc(10);
Then in another function I want to know the size of memory pointed by the ab pointer.
Is there any way that I can know that ab is pointing to 10 chars of memory?
No, you don't have a standard way to do this. You have to pass the size of the pointed-to memory along with the pointer, it's a common solution.
I.e. instead of
void f(char* x)
{
//...
}
use
void f(char *x, size_t length)
{
//....
}
and in your code
char *ab = malloc( 10 );
f( ab, 10 );
It's a deep secret that only free() knows for sure. It's likely in your system, but in a totally implementation dependent manner.
A bit awkward, but if you want to keep everything together:
typedef struct
{ // size of data followed by data (C only trick! NOT for C++)
int dimension; // number of data elements
int data[1]; // variable number of data elements
} malloc_int_t;
malloc_int_t *ab;
int dimension = 10;
ab = malloc( sizeof(*ab) + (dimension-1)*sizeof(int) );
ab->dimension = dimension;
ab->data[n] // data access
I've changed the data type to int to make the code a more generic template.
You can't (portably anyway). You have to keep track of the size yourself.
Some implementations of malloc could give you an API to access that information, but there is no provisions in the standard for this.
The size is what you passed into malloc, you can use a global variable or macro to remember it.
There is no way, you have to store the size of the allocated memory in another variable.
No, unfortunately.
You need to pass the size of the block along with the pointer.
No.
Now, that being said, there are non-portable hacks to do this, but it is not safe to rely upon them.
If you know with 100% certainty that the memory was allocated via malloc(), you may be able to rewind the pointer a few bytes and inspect the 'malloc node' that is used to track which parts of memory have been allocated and which have not. However, I can not stress this enough--do not ever depend upon this.
There is no way to deduce the size of allocated memory from the pointer itself. Since ab is a char *, sizeof(ab) is the same as sizeof(char *), which obviously is not the same as the size of the allocated chunk of memory.
Since you called malloc with the required size, you know what the size is. Pass this number along with the pointer to the function that needs to know the size.
I had a structure and a char pointer pointing to its memory address. So relating it to your question, I wanted to find the size of the memory location it was pointing to i.e. the size of the structure. So logically what you do is, find the size of the object the pointer creates to. This worked for me:
unsigned char * buffer= Library1Structure;
int x=sizeof(Library1Structure);
So the value of x tells me the size of the memory location the pointer buffer points to.

Basic array usage in C?

Is this how you guys get size of an array in ANSI-C99? Seems kind of, um clunky coming from higher language.
int tests[7];
for (int i=0; i<sizeof(tests)/sizeof(int); i++) {
tests[i] = rand();
}
Also this Segmentation faults.
int r = 10000000;
printf ("r: %i\n", r);
int tests[r];
run it:
r: 10000000
Segmentation fault
10000000 seg faults, but 1000000 works.
How do I get more info out of this? What should I be checking and how would I debug something like this? Is there a limit on C arrays? What's a segmentation fault?
Getting size of an array in C is easy. This will give you the size of array in bytes.
sizeof(x)
But I guess what you require is number of elements, in that case it would be:
sizeof(x) / sizeof(x[0])
You can write a simple macro for this:
#define NumElements(x) (sizeof(x) / sizeof(x[0]))
For example:
int a[10];
int size_a = sizeof(a); /* size in bytes */
int numElm = NumElements(a); /* number of elements, here 10 */
Why calculate the size?
Define a constant containing the size and use that when declaring the array. Reference the constant whenever you want the size of the array.
As a primarily C++ programmer, I'll say that historically the constant was often defined as an enum value or a #define. In C, that may be current rather than historic, though - I don't know how current C handles "const".
If you really want to calculate the size, define a macro to do it. There may even be a standard one.
The reason for the segfault is most likely because the array you're trying to declare is about 40 megabytes worth, and is declared as a local variable. Most operating systems limit the size of the stack. Keep your array on the heap or in global memory, and 40 megabytes for one variable will probably be OK for most systems, though some embedded systems may still cry foul. In a language like Java, all objects are on the heap, and only references are kept on the stack. This is a simple and flexible system, but often much less efficient than storing data on the stack (heap allocation overheads, avoidable heap fragmentation, indirect access overheads...).
Arrays in C don't know how big they are, so yes, you have to do the sizeof array / sizeof array[0] trick to get the number of elements in an array.
As for the segfault issue, I'm guessing that you exceeded your stack size by attempting to allocate 10000000 * sizeof int bytes. A rule of thumb is that if you need more than a few hundred bytes, allocate it dynamically using malloc or calloc instead of trying to create a large auto variable:
int r = 10000000;
int *tests = malloc(sizeof *test * r);
Note that you can treat tests as though it were an array type in most circumstances (i.e., you can subscript it, you can pass it to any function that expects an array, etc.), but it is not an array type; it is a pointer type, so the sizeof tests / sizeof tests[0] trick won't work.
Traditionally, an array has a static size. So we can do
#define LEN 10
int arr[LEN];
but not
int len;
scanf("%d", &len);
int arr[len]; // bad!
Since we know the size of an array at compile time, getting the size of an array tends to trivial. We don't need sizeof because we can figure out the size by looking at our declaration.
C++ provides heap arrays, as in
int len;
scanf("%d", &len);
int *arr = new int[len];
but since this involves pointers instead of stack arrays, we have to store the size in a variable which we pass around manually.
I suspect that it is because of integer overflow. Try printing the value using a printf:
printf("%d", 10000000);
If it prints a negative number - that is the issue.
Stack Overflow! Try allocating on the heap instead of the stack.

Resources