difference between allocation [duplicate] - c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between declaration and malloc
Is there a difference between these two programs?
int main(void) {
char str[80];
}
and
int main(void) {
char * str = (char*) malloc( sizeof(char) * 80 );
}
So is there a difference between using malloc and the array-like syntax? So if I need memory for 80 characters, I should use malloc and not the other possibility, right?
I'll try to answer my own question!

char str[80];
allocates 80 bytes on the stack. This will be automatically reclaimed when str goes out of scope.
char * str = (char*) malloc( sizeof(char) * 80 );
allocates 80 bytes on the heap. This memory is available until you call free.
Note that the second case can be simplified to
char * str = malloc(80);
i.e. You should not cast the return from malloc in C and sizeof(char) is guaranteed to be 1

The first is allocated on the stack, and will be free'd when the variable goes out of scope. The second on the heap, and must be free()'d explicitly.
Both can be passed as pointers.

In the first case, you allocate 80 characters on the stack, in the second case you allocate memory on the heap.
Both can be used as pointers, and passed around to functions, and both can be used with array indexing syntax as well.

Related

C malloc syntax [duplicate]

This question already has answers here:
Do I cast the result of malloc?
(29 answers)
Closed 7 years ago.
str = (char *) malloc(15);
If I do not type (char *), is there any difference in my program?
If I try to free the memory with free(str), linux freezes unexpectedly after running program.
If you program in C, it does not make a difference, the preferred syntax is actually
char *str = malloc(15);
If you were programming in C++, the return value from malloc() would not be cast implicitly as char * for storing into str. But in C++, you should not use malloc() anyway, you should write str = new char[15]; and free this memory with delete []str;.
A potential reason for free(str); to cause undefined behavior is your writing to the array pointed to by str beyond the first 15 bytes.
Use valgrind to help track down where this happens.
char *malloc(size)
unsigned size;
malloc() is used to allocate a certain number, size, of free memory and return a pointer to the beginning of it. The malloc() function is part of the dynamic allocation routines.
If an allocation request fails- that is, if there is insufficient memory to fill the request- a null pointer is returned.
You always must be very careful to make sure that you receive a valid pointer from malloc().
This is the general form of a program that will allocate 80 bytes of memory and then free them.
main()
{
char *p;
p= malloc(80);
if(!p){ printf("out of memory\n"); exit(2); }
.
.
.
free(p);
}

How to allocate memory for an array of strings of 10 characters

I have the following variable called lines and want to allocate memory for 10 instances of the variable.
char (*lines)[30];
lines = (char *)malloc(10 * sizeof(char) * 30);
It does not work, I don't know if the issue is with the declaration or allocation. Thanks in advance.
lines = malloc(10*sizeof(*lines));
will do the trick. In fact, the general technique of
pointer = malloc(number_needed * sizeof(*pointer));
is a general way to reduce errors when using malloc(), since sizeof(*pointer) always gives the size of the elements needed.
However, that is a C technique (just as your question is really C, not C++).
In C++, you would be better off in C++ doing
std::string lines[10];
or (if you want the option to dynamically change the number of lines at run time)
std::vector<std::string> lines(10);
std::string and std::vector are declared in the standard headers <string> and <vector> respectively.
char (*lines)[30] declares lines as pointer to array of 30 char. If you want to allocate 10 elements of such array, the allocation should be done as follows:
char (*lines)[30] = malloc( 10 * sizeof( *lines ) );
I guess you want to allocate 10 arrarys, whose length is 30 characters long for each, with only one malloc() function call. You must be intend to use the variable 'lines' as an index for the allocated memory, since the allocated memory is actually an array of 10*30=300 chracters.
What you have to check is the type cast of the malloc() function. The variable 'line' is a pointer to 30 chracters, whereas your type casting before malloc() is poting a char.
lines = malloc(10 * sizeof(char) * 30);

Amount of memory to allocate to array of strings?

I have a char** which is designed to hold and unknown amount of strings with unknown length
I've initially allocated 10 bytes using
char **array = malloc(10);
and similarly, before adding strings to this array, I allocate
array[num] = malloc(strlen(source)+1)
I've noticed that my program crashes upon adding the 6th element to the array
My question is, how does memory with these arrays work? When I allocated 20 bytes, nothing happened, yet when I allocated 30, it suddenly could hold 10 elements. These were all strings of 2-3 characters in size. I'm struggling to think of a condition to realloc memory with, e.g
if condition{
memoryofarray += x amount
realloc(array, memoryofarray)
}
What exactly uses the memory in the char**? I was under the impression that each byte corresponds to how many lines they can hold, i.e. malloc(10) would allow the array to hold 10 strings. I need to know this to establish conditions + to know how much to increment the memory allocated to the array by.
Also, curiously, when I malloced
array[num] = malloc(0)
before assigning a string to that array element, it worked without problems. Don't you need to at least have strlen amount of bytes to store strings? This is confusing me massively
This line:
char **array = malloc(10);
allocates 10 bytes, however, remember that a pointer is not the same size as a byte.
Therefore you need to make sure you allocate an array of sufficient size by using the size of the related type:
char **array = malloc(10 * sizeof(char*));
Now that you have an array of 10 pointers you need to allocate memory for each of the 10 strings, e.g.
array[0] = malloc(25 * sizeof(char));
Here sizeof(char) is not needed but I added it to make it more obvious how malloc works.
If you want to hold 10 strings then you need to allocate memory for 10 char *'s and then allocate memory to those char pointers .You allocate memory of 10 bytes( not enough for 10 char *'s ) .Allocate like this -
char **array = malloc(10*sizeof(char *)); // allocate memory for 10 char *'s
And then do what you were doing -
array[num] = malloc(strlen(source)+1) // allocate desired memory to each pointer
note - take care that num is initialized and does not access out of bound index.
This will allocate enough memory for 10 pointers to char (char*) in array
char **array = malloc(10*sizeof(array[0]));
On a 64bit system the size of a char* is 8 bytes = 64 bits. The size of a char is typically 1 byte = 8 bits.
The advantage of using sizeof(array[0]) instead sizeof(char*) is that it's easier to change the type of array in the future.
char** is pointer to a pointer to char. It may point to the start of a memory block in the heap with pointers to char. Similarly char* is a pointer to char and it may point to the start of a memory block of char on the heap.
If you write beyond the allocated memory you get undefined behaviour. If you are lucky it may actually behave well! So when you do for example :
array[num] = malloc(0);
you may randomly not get a segmentation fault out of (good) luck.
Your use of realloc is wrong. realloc may have to move the memory block whose size you want to increase in which case it will return a new pointer. Use it like this :
if (condition) {
memoryofarray += amount;
array = realloc(array, memoryofarray);
}
Rather than allocating memory using the fault-prone style
pointer = malloc(n); // or
pointer = malloc(n * sizeof(type_of_pointer));
Use
pointer = malloc(sizeof *pointer * n);
Then
// Bad: certainly fails to allocate memory for 10 `char *` pointers
// char **array = malloc(10);
// Good
char **array = malloc(sizeof *array * 10);
how does memory with these arrays work?
If insufficient memory is allocated, it does not work. So step 1: allocate sufficient memory.
Concerning array[num] = malloc(0). An allocation of 0 may return NULL or a pointer to no writable memory or a pointer to some writable memory. Writing to that pointer memory is undefined behavior (UB) in any of the 3 cases. Code may crash, may "work", it is simply UB. Code must not attempt writing to that pointer.
To be clear: "worked without problems" does not mean code is correct. C is coding without a net. Should code do something wrong (UB), the language is not obliged to catch that error. So follow safe programming practices.
First allocate an array of pointers:
char* (*array)[n] = malloc( sizeof(*array) );
Then for each item in the array, allocate the variable-length strings individually:
for(size_t i=0; i<n; i++)
{
(*array)[i] = malloc( some_string_length );
}

Understanding code with use of the malloc() function and pointers

I'm trying to document some code to improve my knowledge of pointers and general ANSI C ability.
...
int static_store = 30;
const char * pcg = "String Literal";
int main()
{
int auto_store = 40;
char auto_string[] = "Auto char Array";
int * pi;
char * pcl;
pi = (int *) malloc(sizeof(int));
*pi = 35;
pcl = (char *) malloc(strlen("Dynamic String") + 1);
strcpy(pcl, "Dynamic String");
...
From first looks, two pointers are initialised, pi and pcl, of type int and char respectively.
But the lines after are confusing to me and I don't understand what is happening. I can see that malloc is being called to allocate memory the size of int (40). Is it assigning memory to the variables pi and pcl?
Is it assigning memory to the variables pi and pcl?
Yes malloc is allocating memory to these pointers.
pi is allocated memory equal to sizeof(int)(that may vary) and pcl has be allocated memory equal to length of string plus 1(plus 1 for null character).
From first looks, two pointers are initialised, pi and pcl, of type int and char respectively
They are declared not initialized.
Note- Please don't cast return of malloc
2 pointers are delcared (pi and pcl). At declaration they are not intialized.
pi is then pointed to a block of heap allocated memory that can hold 1 int (the size of this is platform dependant but it would usually be 4 bytes) allocated with the fucntion maloc. Somewhere this memory will have to be explicitely freed with the funtion free - failing to do so will be a memory leak.
The int value 35 is then stored at that memory location. *pi can be read as "what the pointer pi points to" it is effectively the same as pi[0].
pcl is then pointed to a block of heap allocated memory that is large enough to hold 14 char plus a '\0' char (i.e 15 bytes) using the function malloc (as above at some point this memory must be freed).
The 15 characters "Dynamic String\0" is then put in that memory using the function strcpy.
The line:
pi = (int *) malloc(sizeof(int))
Actually allocate memory for one int variable. The line afterwards, puts the value 35 into that variable.
The line:
pcl = (char *) malloc(strlen("Dynamic String") + 1)
Creates a dynamically allocated char array (which is equivalent to a string). The size of that array is of the length of the string ("Dynamic String") plus one. The next line copies the string: "Dynamic String" into the allocated array. The plus one is needed because each string in c ends with the char '\0' which is a sign for the end of a string.
The malloc function reserves a block of memory in the heap (the dynamic memory pool), and returns a pointer to the first element of that block of memory. That memory is reserved until you call free, or the program exits.
In the call
pi = (int *) malloc(sizeof(int));
malloc reserves a block of memory large enough to store a single int value, and the pointer to that memory block is assigned to pi. You do not need to cast the result of malloc1, and it's actually considered bad practice2. A better way to write that would be
pi = malloc( sizeof *pi );
The expression *pi has type int, so sizeof *pi is equivalent to sizeof (int)3. The advantage of using sizeof *pi over sizeof (int) (as well as dropping the cast) is that if you ever change the type of pi (from int * to long *, for example), you won't have to change anything in the malloc call; it will always allocate the right amount of memory regardless of the type of pi. It's one less maintenance headache to worry about.
Similarly, the call
pcl = (char *) malloc(strlen("Dynamic String") + 1);
reserves enough memory to hold the contents of "Dynamic String" (the +1 is necessary for the string terminator) and assigns the pointer to that memory to pcl. Again, this would be better written as
pcl = malloc( strlen("Dynamic String") + 1 ); // no cast
sizeof (char) is 1 by definition, so you don't need an explicit sizeof *pcl in the call above; however, if you ever decide to change the type of pcl from char * to wchar_t *, it would be good to have it in place, although you'd still have to change the string literal and change how you compute the length, so it's not maintenance-free.
The general form a malloc call is
T *p = malloc( num_elements * sizeof *p ); // where num_elements > 1
or
T *p;
...
p = malloc( num_elements * sizeof *p );
There is a similar function named calloc that will zero out the allocated memory block:
T *p = calloc( num_elements, sizeof *p );
or
T *p;
...
p = calloc( num_elements, sizeof *p );
1. In C, anyway; C++ does require the cast, since C++ does not allow implicit conversions between void * and other pointer types. But you shouldn't be using malloc in C++ code, anyway.
So why do people still cast the result of malloc in C? It's largely a holdover from pre-ANSI days (more than a quarter of a century ago), when malloc returned char *, which cannot be assigned to a different pointer type without a cast. The 1989 standard introduced the void * type, which is essentially a "generic" pointer that can be assigned to other pointer types without an explicit cast.
2. Under the C89 standard, if the compiler sees a function call without having seen a declaration for that function, it will assume that the function returns int. Thus, if you forget to include stdlib.h or otherwise don't have a declaration for malloc in scope, the compiler will assume it returns an int value and generate the machine code for the call accordingly. However, int and pointer types aren't compatible, and normally the compiler will issue diagnostic if you try to assign one to the other. By using the cast, however, you supress that diagnostic, and you may run into runtime problems later on.
The 1999 standard did away with implicit int typing for functions, so that's not really a problem anymore, but the cast is still unnecessary and leads to maintenance problems.
3. sizeof is an operator, not a function; parentheses are only required if the operand is a type name like int or double or struct blah.

Is mallocing equivalent to pointer with a specified array size

I've read various tutorials on pointers, and I now come with a question,
is this:
char *input = malloc(sizeof(char)*24);
the same as
char *input[24];
I was under the impression that the malloc will also create my space on the heap with 24 slots. Usually, I see char input[24], but the char *input[24] I figured was a simpler way than mallocing.
Thanks!
No, they are not the same.
char *input = malloc(sizeof(char)*24);
will allocate a block of 24 char's on the heap and assign a pointer to the start of that block to input. (technically you are just telling it to allocate x number of bytes where x is 24 times the size, in bytes, of each char)
char *input[24];
will create an array of 24 char pointers on the stack. These pointers will not point to anything (or garbage on init) as you have it written.
For the second example, you could then take each pointer in the array input and allocate something for it to point to on the heap. Ex:
char *input[NUM_STRS];
for( int i = 0; i < NUM_STRS; i++ )
{
input[i] = malloc( MAX_STR_LEN * sizeof(char) );
}
Then you would have an array of character pointers on the stack. Each one of these pointers would point to a block of characters on the heap.
Keep in mind, however, that things on the stack will be popped off when the function exits and that variable goes out of scope. If you malloc something, that pointer will be valid until it is freed, but the same is not true of an array created on the stack.
EDIT:
Based on your comment, here is an example of making 24 character pointers on the heap and allocating space for them to point to:
#define NUM_STRS 24
#define MAX_STR_LEN 32
char **input = malloc( sizeof(char *) * NUM_STRS );
for( int i = 0; i < NUM_STRS; i++ )
{
input[i] = malloc( sizeof(char) * MAX_STR_LEN );
}
Please keep in mind that with this example you will have to free each pointer in input, and then input itself at the appropriate time to avoid leaking memory.
These are not the same at all.
char *input = malloc(sizeof(char)*24);
This allocates enough memory to hold 24 char, and assigns the address to input (a pointer). This memory is dynamically-allocated, so it needs to be released at some point with an appropriate call to free().
char *input[24];
This declares input to be an array of 24 pointers. This has automatic storage, which means you do not need to free it. (However, you may need to free the things being pointed to by each of the pointers, but that's a different matter!)
Fundamentally, the types of the two variables are different. In the first case, you declare a pointer to char that points to memory dynamically allocated by malloc (which you are morally obligated to free at a later instant). In the second case, you declare an array of pointers to char.
Couple of observations:
sizeof(char) is one by definition, so you can leave that out. (No, it does not convey a documenting purpose. You are better of rewriting it as char *input = malloc( 24 * sizeof *input );)
Very seldom will the call to malloc have an integer literal. If it does (24) in your example, then usually one would prefer to have an array to hold that (there are some considerations regarding stack usage that I am side-stepping here).
hope this helps,
You can compare it better to char input[24]; (note no *). With that you can use input in the same way but the memory is on the stack instead of on the heap.

Resources