Need some explanation about malloc - c

I don't understand it prints out OneExample when i allocated memory for 5.
I know it is possible to do it using strncpy
But is there a way to do it without using strncpy
It works with strncpy, but is there a way to do it without strncpy ?
void main()
{
char *a;
a=(char*)malloc(5);
a="OneExample";
printf("%s",a);
free(a);
}
It prints out OneExample
Should not it print OneE ??
Can someone explain ?
void main()
{
char *a;
a=(char*)malloc(5);
a="OneExample";
printf("%s",a);
free(a);
}

You aren't using the memory you've allocated. After allocating the memory, you override the pointer a with a pointer to a string literal, causing a memory leak. The subsequent call to free may also crash your application since you're calling free on a pointer that was not allocated with malloc.
If you want to use the space you allocated, you could copy in to it (e..g, by using strncpy).

I don't understand it prints out OneExample when i allocated memory for 5. I know it is possible to do it using strncpy But is there a way to do it without using strncpy
It works with strncpy, but is there a way to do it without strncpy ?
You can use memcpy() as an alternative.
Read about memcpy() and check this also.
Seems that you have some misunderstanding about pointers in C.
Look at this part of your code:
a=(char*)malloc(5);
a="OneExample";
printf("%s",a);
free(a);
You are allocating memory to char pointer a and then immediately pointing it to the string literal OneExample.
This is memory leak in your code because you have lost the reference of the allocated memory.
You should be aware of that the free() deallocates the space previously allocated by malloc(), calloc() or realloc() otherwise the behavior is undefined.
In your program, you are trying to free memory of string literal "OneExample" which will lead to undefined behavior.
Using memcpy(), you can do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void) {
char *a = malloc(5);
if (a == NULL) {
fprintf (stderr, "Failed to allocate memory\n");
exit(EXIT_FAILURE);
}
memcpy (a, "OneExample", 4); // copy 4 characters to a, leaving space for null terminating character
a[4] = '\0'; // make sure to add null terminating character at the end of string
printf("%s\n",a);
free(a);
return 0;
}
Additional:
Using void as return type of main function is not as per standards. The return type of main function should be int.
Follow good programming practice, always check the malloc return.
Do not cast the malloc return.

To use malloc, you need to #include <stdlib.h> which you don't show in your code. The reason is that malloc has a prototype returning a void * and without that prototype, your compiler is going to assume it returns an int. In 64bit architectures, this is a problem, as void * is a 64bit type, and int is 32bit. This makes that the code that extracts the value returned by malloc() to take only the 32 less signifiant bits of the result, and then convert them to a pointer (as per the cast you do, that you shouldn't ---see a lot of comments about this---, and you'll avoid the error you should have got, about trying to convert a int value into a char * without a cast)
After assigning the pointer given by malloc(3) into a, you overwrite that pointer with the address of the string literal "OneExample". This makes two things:
First, you lose the pointer value given by malloc(3) and that was stored in a so you don't have it anymore, and you'll never be able to free(3) it. This is called a memory leak, and you should avoid those, as they are programming errors.
This will be making some kind of undefined behaviour in the call to free(3) that only accepts as parameter a pointer value previously returned by malloc (and this is not the actual address stored in a) Probably you got some SIGSEGV interrupt and your program crashed from this call.
When you do the assignment to a, you are just changing the pointer value that you stored in there, and not the deferred memory contents, so that's what makes sense in calling strcpy(3), because it's the only means to copy a string of characters around. Or you can copy the characters one by one, as in:
char *a = malloc(5); /* this makes a memory buffer of 5 char available through a */
int i;
for(i = 0; i < 4 /* see below */; i++)
a[i] = "OneExample"[i]; /* this is the copy of the char at pos i */
a[i] = '\0'; /* we must terminate the string if we want to print it */
the last step, is what makes it necessary to run the for loop while i < 4 and not while i < 5, as we asked malloc() for five characters, and that must include the string terminator char.
There's one standard library alternative to this, and it is:
char *a = strdup("OneExample");
which is equivalent to:
#define S "OneExample"
char *a = malloc(strlen(S) + 1); /* see the +1 to allow for the null terminator */
strcpy(a, S);
but if you want to solve your example with the truncation of the string at 5, you can do the following:
char *dup_truncated_at(const char *s, int at)
{
char *result = malloc(at + 1); /* the size we need */
memcpy(result, s, at); /* copy the first at chars to the position returned by malloc() */
result[at] = '\0'; /* and put the string terminator */
return result; /* return the pointer, that must be freed with free() */
}
and you'll be able to call it as:
char *a = dup_truncated_at("OneExample", 5);
printf("truncated %s\n", a);
free(a); /* remember, the value returned from dup_truncated_at has been obtained with a call to malloc() */

You need to be clear about what your pointer points to. First, you declare a char *a;. This is a pointer to a character.
In the line a=(char*)malloc(5);, you allocate a bit of memory with malloc and assign the location of that memory to the pointer a. (a bit colloquial, but you understand what I mean). So now a points to 5 bytes of freshly allocated memory.
Next, a="OneExample";. a gets a new value, namely the location of the string OneExample; There is now no longer a pointer available to the five bytes that were allocated. They are now orphans. a points to a string in a static context. Depending on the architecture, compiler and a lot of other things, this may be a static data space, program space or something like that. At least not part of the memory that is used for variables.
So when you do printf("%s",a);, a points to the string, and printf will print-out the string (the complete string).
When you do a free(a);, you are trying to free a part of the program, data etc space. That is, in general, not allowed. You should get an error message for that; in Linux that will be something like this:
*** Error in `./try': free(): invalid pointer: 0x000000000040081c ***
======= Backtrace: =========
/lib64/libc.so.6(+0x776f4)[0x7f915c1ca6f4]
/lib64/libc.so.6(+0x7ff4a)[0x7f915c1d2f4a]
/lib64/libc.so.6(cfree+0x4c)[0x7f915c1d6c1c]
./try[0x400740]
/lib64/libc.so.6(__libc_start_main+0xf0)[0x7f915c1737d0]
./try[0x4005c9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 21763273 /home/ljm/src/try
00600000-00601000 r--p 00000000 08:01 21763273 /home/ljm/src/try
00601000-00602000 rw-p 00001000 08:01 21763273 /home/ljm/src/try
[- more lines -]

The statement a="OneExample"; does not mean “Copy the string "OneExample" into a.”
In C, a string literal like "OneExample" is an array of char that the compiler allocates for you. When used in an expression, the array automatically becomes a pointer to its first element.1
So a="OneExample" means “Set the pointer a to point to the first char in "OneExample".”
Now, a is pointing to the string, and printf of course prints it.
Then free(a) is wrong because it attempts to free the memory of "OneExample" instead of the memory provided malloc.
Footnote
1 This automatic conversion does not occur when a string literal is the operand of sizeof, is the operand of unary &, or is used to initialize an array.

the = does not copy the string only assigns the the new value to the pointer overriding the old one. You need to allocate sufficient memory to store the string and then copy it into the allocated space
#define MYTEXT "This string will be copied"
char *a = malloc(strlen(MYTEXT) + 1); //+1 because you need to store the trailing zero
strcpy(a,MYTEXT);
then you can free a when not needed anymore

Firstly here
a=(char*)malloc(5);
you have allocated 5 bytes of memory from heap and immediately
a="OneExample";
override previous dynamic memory with string literal "OneExample" base address due to that a no longer points to any dynamic memory, it causes memory leak(as no objects points that dynamic memory, it lost) here and even after that
free(a);
freeing not-dynamically allocated memory causes undefined behavior.
side note, do read this Why does malloc allocate more memory spaces than I ask for & Malloc vs custom allocator: Malloc has a lot of overhead. Why? to get some more info about malloc().

Related

Invalid (Aborted)core dumped error while using free() in C

here's the code:
can anyone explain this issue
how can i deallocate the memory of s in main
char *get(int N)
{
char *s=malloc(10*sizeof(char));
s="hello";
return s;
}
int main()
{
char *s=get(4);
printf(s);
free(s);
}
This here:
s="hello";
Doesn't write "hello" to the allocated memory. Instead, it reassigns s to point to a read-only place where "hello" is stored. The memory you allocated with malloc is leaked, and the free(s); is invalid, because you can't free that read-only memory.
If you want to copy "hello" into s, try strcpy(s,"hello"); instead.
By doing
s="hello";
you're overwriting the returned pointer by malloc() with the pointer to the first element of the string literal "hello", which is not allocated dynamically.
Next, you are passing that pointer (to a string literal) to free(), which causes the undefined behavior.
You may want to change the assignment to
strcpy(s, "hello");
Additionally, by overwriting the originally returned pointer by malloc(), you don't have a chance to deallocate the memory - so you also cause memory leak.
You have two bugs here:
You reassign the pointer s with the reference of the string literal "hello", loosing the memory allocated by malloc
You allocate not enough space for the "hello" string. You need at least 6 characters (not 4)
A variable of type char * is a pointer (memory address) to a character. In C, it is customary to implement strings as zero-terminated character arrays and to handle strings by using variables of type char * to the first element of such an array.
That way, variables of type char * do not actually contain the strings, they merely point to them.
For this reason, the line
s="hello";
does not actually copy the contents of the string, but rather only the pointer (i.e. the memory address) of the string.
If you want to copy the actual contents of the string, you must use the function strcpy instead.
By overwriting the pointer that you use to store the address of the memory allocated by malloc, you are instead passing the address of the string literal "hello" to free. This should not be done. You must instead only pass memory addresses to free that you received from malloc.

What is the difference between using strcpy and equating the addresses of strings?

I am not able to understand the difference between strcpy function and the method of equating the addresses of the strings using a pointer.The code given below would make my issue more clear. Any help would be appreciated.
//code to take input of strings in an array of pointers
#include <stdio.h>
#include <strings.h>
int main()
{
//suppose the array of pointers is of 10 elements
char *strings[10],string[50],*p;
int length;
//proper method to take inputs:
for(i=0;i<10;i++)
{
scanf(" %49[^\n]",string);
length = strlen(string);
p = (char *)malloc(length+1);
strcpy(p,string);//why use strcpy here instead of p = string
strings[i] = p; //why use this long way instead of writing directly strcpy(strings[i],string) by first defining malloc for strings[i]
}
return 0;
}
A short introduction into the magic of pointers:
char *strings[10],string[50],*p;
These are three variables with distinct types:
char *strings[10]; // an array of 10 pointers to char
char string[50]; // an array of 50 char
char *p; // a pointer to char
Then the followin is done (10 times):
scanf(" %49[^\n]",string);
Read C string from input and store it into string considering that a 0 terminator must fit in also.
length = strlen(string);
Count non-0 characters until 0 terminator is found and store in length.
p = (char *)malloc(length+1);
Allocate memory on heap with length + 1 (for 0 terminator) and store address of that memory in p. (malloc() might fail. A check if (p != NULL) wouldn't hurt.)
strcpy(p,string);//why use strcpy here instead of p = string
Copy C string in string to memory pointed in p. strcpy() copies until (inclusive) 0 terminator is found in source.
strings[i] = p;
Assign p (the pointer to memory) to strings[i]. (After assignment strings[i] points to the same memory than p. The assignment is a pointer assignment but not the assignment of the value to which is pointed.)
Why strcpy(p,string); instead of p = string:
The latter would assign address of string (the local variable, probably stored on stack) to p.
The address of allocated memory (with malloc()) would have been lost. (This introduces a memory leak - memory in heap which cannot be addressed by any pointer in code.)
p would now point to the local variable in string (for every iteration in for loop). Hence afterwards, all entries of strings[10] would point to string finally.
char *strings[10]---- --------->1.
strcpy(strings[i],string) ----->2.
strings[i] = string ----------->3.
p = (char *)malloc(length+1); -|
strcpy(p,string); |-> 4.
strings[i] = p;----------------|
strings is an array of pointers, each pointer must point to valid memory.
Will lead undefined behavior since strings[i] is not pointing to valid memory.
Works but every pointer of strings will point to same location thus each will have same contents.
Thus create the new memory first, copy the contents to it and assign that memory to strings[i]
strcpy copies a particular string into allocated memory. Assigning pointers doesn't actually copy the string, just sets the second pointer variable to the same value as the first.
strcpy(char *destination, char *source);
copies from source to destination until the function finds '\0'. This function is not secure and should not be used - try strncpy or strlcpy instead. You can find useful information about these two functions at https://linux.die.net/man/3/strncpy - check where your code is going to run in order to help you choose the best option.
In your code block you have this declaration
char *strings[10],string[50],*p;
This declares three pointers, but they are quite different. *p is an ordinary pointer, and must have space allocated for it (via malloc) before you can use it. string[50] is also a pointer, but of length 50 (characters, usually 1 byte) - and it's allocated on the function stack directly so you can use it right away (though the very first use of it should be to zero out the memory unless you've used a zeroing allocator like Solaris' calloc. Finally, *strings[10] is a double pointer - you have allocated an array of 10 pointers, each element of which (strings[1], strings[9] etc) must be allocated for before use.
The only one of those which you can assign to immediately is string, because the space is already allocated. Each of those pointers can be addressed via subscripts - but in each case you must ensure that you do not walk off the end otherwise you'll incur a SIGSEGV "segmentation violation" and your program will crash. Or at least, it should, but you might instead get merely weird results.
Finally, pointers allocated to must be freed manually otherwise you'll have memory leaks. Items allocated on the stack (string) do not need to be freed because the compiler handles that for you when the function ends.

Why can I assign a longer string to a pointer in C?

#include <stdio.h>
#include <stdlib.h>
int main()
{
char *ptr = malloc(sizeof(char) * 1);
ptr = "Hello World";
puts(ptr);
getchar();
}
im not a malloc() expert but isn't that code supposed to give an error since i allocated only one byte but assigned a value that contains 11 bytes to *ptr pointer ?
or does the H get stored in the place i assigned and then the rest of the string just goes in the places after it ?
You are reassigning the pointer 'ptr' to another block of memory, so you won't see any error. However, the block of memory (size 1) that you allocated is "lost" and leads to a memory leak.
When using malloc you're requesting some memory and malloc returns the first address of that memory (if it can be given). When you re-assign the pointer you're not doing anything with the memory it points to. You just change what the pointer points to.
What you're doing here is technically valid C but you're creating a memory leak because you lose the address of the malloced memory, which you must free when you're done with it.

Where are character arrays in dynamically allocated structs stored? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C Array Instantiation - Stack or Heap Allocation?
When dynamically allocating a struct containing a char pointer, what happens with the actual char pointer? Where is it stored?
And once the struct is freed, is the char pointer freed along with it?
For example consider the following struct:
struct mix
{
int a;
float b;
char *s;
};
typedef struct mix mix;
And then the following code that allocates memory for it:
int main()
{
mix *ptr = (mix*)malloc(sizeof(mix));
ptr->a = 3;
ptr->b = 4.5f;
ptr->s = "Hi, there, I'm just a really long string.";
free(ptr);
return 0;
}
Is *s allocated on the stack and then freed along with *ptr? I can imagine it is indeed allocated on the stack as it's not in any way dynamically allocated (unless malloc has some functionality I'm not aware of). And I guess 'going out of scope' for *s would be at the point of freeing *ptr. Or have I got it completely wrong? :)
Thanks very much!
The space for the char* member named s is allocated on the heap, along with the rest of the members of mix after the call to malloc() (whose return value you do not need to cast). The string literal to which s is assigned is not allocated on the heap or the stack, but is part of the actual binary and has static storage duration. So this:
ptr->s = "Hi, there, I'm just a really long string.";
assigns the address of the string literal to ptr->s. If you want ptr->s to point to something other than a string literal then you need to malloc() memory for it. And for every malloc() there must be a free() so ptr->s would need to be free()d before ptr is (if ptr->s is pointing to dynamically allocate memory only).
After the call to free(), dereferencing ptr is undefined behaviour.
When you dynamically allocate mix with malloc(), you are actually allocating a block of memory to store mix structure data members, i.e.
an int (a)
a float (b)
a pointer to a char (s)
And when you call free(), you just release that block.
So, you don't allocate the string, you just allocate the string pointer.
If you want to dynamically allocate the string, you must do it explicitly (with another call to malloc()), and to avoid memory leaks you should also free the string explicitly, using free().
When you malloc for ptr, memory is allocated for all members of the struct including the pointer s which is no different to memory allocated for any other member of the struct.
You are assigning a string literal to s, so it's fine which is usually stored in the read-only section. Otherwise, you'll need to malloc for the ptr->s as well and free. Since, it's a string literal, there's no need to free s here (doing so is UB).
mix* ptr is allocated on the stack. The contents that ptr point at, a variable of type mix, is allocated dynamically on the heap, including the pointer s.
Please note that s doesn't point at anything, the pointer doesn't do anything useful. You have to set it to point at something, which could be allocated anywhere. Whatever it points to is not freed when your struct is freed. In this case you set it to point at a constant string literal allocated in ROM, so you won't need to worry about that.
Is *s allocated on the stack
*s (that is, the result of dereferencing the pointer s) isn't allocated at all. Following the malloc, ptr->s is an uninitialized pointer. It doesn't point to anything, and the expression *(ptr->s) has undefined behavior until you do ptr->s = "Hi, etc".
Once you've initialized ptr->s to point to the string literal, *(ptr->s) is the first character of the string literal, so it probably exists in some data section of the executable. Nothing is dynamically allocated other than the sizeof(mix) bytes for the struct (probably 12 bytes on a 32bit implementation).
what happens with the actual char pointer? Where is it stored?
char* is also like other members, take some bytes(take 8 byte in 64 bit machine, similar to other pointer). In your case, you are allocating memory for that structure instance in heap. so the memory for this pointer also will be allocated in same heap block which is allocated for that structure instance.
Consider this code. This gives where the char* will be:
#include <stdio.h>
typedef struct
{
int a;
float b;
char *s;
}mix;
int main()
{
printf("\n%d ,float:%d, int:%d, char*:%d", sizeof(mix), sizeof(float), sizeof(int), sizeof(char*));
return 0;
}
so size of this structure is 16 bytes. consist of 4 byte integer, 4 byte float and 8 byte char*. (In 64 bit OS, char* will be 4 bytes if OS is 32 bit.)
And once the struct is freed, is the char pointer freed along with it?
Usually the block which is pointed by char* will not be freed(If it points to a block allocated by malloc()). only the structure block will be freed. we know free() needs valid address which is returned during allocation for peaceful de-allocation. If you free without freeing that char*, it will leads to memory leak.
But your case "Hi, there, I'm just a really long string.";
the above given string is string literal which is allocated in read-only section of your program.
use gcc -S Yourprogram.c
This will generate .s file. You can look at .read_only section for this string. so even you delete your structure instance, there will be no memory leak. Because you are just pointing a address which is read-only. You are not at-all allocating memory for this string.

realloc() Failure

I was trying to implement a simple function that can concatenate any number of strings passed to it. My call to realloc fails. Is it something to do with the fact that the string arguments that i pass to the function are stored in data segment where as realloc looks to allocate memory from the heap ? This is just an idea i have. I'm a beginner so please excuse if it seems stupid. How can i make this function run ?
//Program to implement a function that can concatenate any number of argumnets
#include<stdio.h>
#include<stdarg.h>
#include<string.h>
#include<stdlib.h>
char *mstrcat(char *first, ...);
int main(int argc, int **argv){
char *s;
s=mstrcat("I ","Love ","Stack","Overflow");
printf("%s\n",s);
}
char *mstrcat(char *first, ...){
char *s=first,*p;
int len=0; // stores the length of the string as it grows
len=strlen(s);
va_list aptr; // creates a pointer to the unnamed argument list
va_start(aptr,first); // initialise aptr to the first unnamed argument
if(aptr==NULL){
return s;
}
while((p=va_arg(aptr,char *))!=NULL){ // till there are no more arguments to process
len+=strlen(p);
if((s=(char *)realloc(s,len+1))!=NULL){
strcat(s,p);
}
else{
printf("Failed to concatenate\n");
return first;
}
}
return s;
}
Your code has an Undefined Behavior. The standard mandates that the pointer being passed to realloc should exactly match the pointer which was allocated dynamic memory using a memory management function. Memory management functions specified by the standard are:
aligned_alloc, calloc, malloc, and realloc.
The pointer you are passing to realloc() was not returned by any of these and hence the Undefined Behavior.
Reference:
c99 standard: 7.22.3.5 The realloc function
Synopsis: #1
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
#3
If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined. If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
A point about realloc, the size argument is new size of the allocated data, which for you should be the old length of s plus the length of p (+1 for the terminator of course).
And as you suspect, you can not use the first string as the base of the reallocations. Instead set s to NULL at the start of the function.
You are passing string literals to your mstrcat function, and they are probably stored in a read-only area of the process, which means that they cannot be modified or resized.
realloc can only be used with a pointer previously returned by malloc or realloc. Other kinds of uses (as is yours) yield undefined behaviour.
the mstrcat function is starting with s pointing to the first argument. Then you are trying to realloc() this pointer which is a static string. This will not work. You can only realloc a pointer previously allocated by malloc().
I suggest you change char *s=first to char *s=strdup(first) to allocate a copy of the first argument, and then this code should work.
The concatenation algorithm is pretty inefficient, but that's another story... (hint: you may want to enumerate the arguments and keep track of the total size, then alloc() a corresponding buffer and then concatenate all the arguments into it)

Resources