Getting core dump freeing memory allocated by getline() - c

I am getting the core dump and I have been looking and it seems I am doing everything right.
int len = 0;
char *buff = NULL;
size_t sz;
if(getline(&buff,&sz, stdin) > 0){
while(isalpha(*buff++))
++len;
printf(" 1st word %d characters long ",len);
}
free(buff);

In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
You fail in (1) so you can't do (2). Specifically, what is happening is getline() allocates storage and assigns the beginning address for the allocated block to buff. You then use buff to iterate over the string calling *buff++. When you are done iterating, buff no longer points to (holds the beginning address of) the block of memory allocated by getline().
When you attempt to pass buff to free(), an error occurs because you are attempting to free an address that was not previously allocated by malloc, calloc or realloc.
Use a separate pointer to iterate with, e.g. char *p = buff; within your read loop and iterate with p. (you can also use an index for iterating, e.g. buf[i] without changing the original address buff holds) Then you can pass buff to free().

Related

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.

Need some explanation about malloc

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().

How free memory after of realloc

Is correct ways to free up memory in this code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void ){
char *string1, *string2;
string1 = (char*) malloc(16);
strcpy(string1, "0123456789AB");
string2 = realloc(string1, 8);
printf("string1 Valor: %p [%s]\n", string1, string1);
printf("string2 Valor: %p [%s]\n", string2, string2);
free(string1);
free(string2);
return 0;
}
Since the two pointers point to the same direction
I think your confusion comes from the (uninspired) expression "free pointers" (you used in your post, but edited it out since). You don't free pointers. You free memory. The pointer is just telling which memory.
In your example you have: the memory obtained from malloc. string1 points to this memory. Then when you call realloc a new memory block is obtained (possibly starting at the same address, possibly not), but realloc takes care to release the old one if needed (and is therefore undefined behavior to access or free it yourself). string2 points to this new memory block.
So you have to free just the memory block obtained from realloc. string2 points to that memory.
In short, no.
Per the C Standard:
7.22.3.5 The realloc function
...
The realloc function deallocates the old object pointed to
by ptr and returns a pointer to a new object that has the
size specified by size. The contents of the new object shall
be the same as that of the old object prior to deallocation, up to the
lesser of the new and old sizes. Any bytes in the new object beyond
the size of the old object have indeterminate values.
Once you call realloc(), you do not have to free() the memory addressed by pointer passed to realloc() - you have to free() the memory addressed by the pointer realloc() returns. (Unless realloc() returns NULL, in which case the original block of memory - passed to realloc() - has to be free()'d.)
When you call realloc, either the returned pointer is the same as the original, or a new pointer is returned and the original pointer becomes invalid. In the first case, calling free on both string1 and string2 results in a double-free since the pointers are equal. In the second case, calling free on string1 is a double-free since it was already freed.
So either way you have a double-free which results in undefined behavior.
From the man page for realloc:
void *realloc(void *ptr, size_t size);
The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range
from the start of the region up to the minimum of the old and new
sizes. If the new size is larger than the old size, the added memory
will not be initialized. If ptr is NULL, then the call is equivalent
to malloc(size), for all values of size; if size is equal to zero, and
ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr
is NULL, it must have been returned by an earlier call to malloc(),
calloc() or realloc(). If the area pointed to was moved, a free(ptr)
is done.
The realloc() function returns a pointer to the newly allocated
memory, which is suitably aligned for any kind of variable and may be
different from ptr, or NULL if the request fails.
Also from the man page for free:
The free() function frees the memory space pointed to by ptr, which
must have been returned by a previous call to malloc(), calloc() or
realloc(). Otherwise, or if free(ptr) has already been called before,
undefined behavior occurs. If ptr is NULL, no operation is performed.
You only need to free(string2).
Short answer: in your code, calling free(string2) is correct, and sufficient. Calling free(string1) is incorrect.
When you called realloc (and assuming that the call succeeded), its return value (which you stored in string2) became the one and only way to refer to the one block of memory that you have.
It may be that realloc resized your memory block "in place", meaning that the values of string2 and string1 are equal. In that case, calling free(string1) is wrong because you're freeing the same pointer twice.
It may be that realloc moved your data to a new place in the process of resizing it. In that case, the values of string2 and string1 are unequal. But in that case, after it finds a new place for your data and copies it there, realloc automatically frees the old block for you. So, again, calling free(string1) is wrong because you're freeing an already-freed pointer.
Think of realloc as something equivalent to:
void *
realloc(void *old, size_t new_size)
{
size_t old_size = magic_internal_function_that_knows_the_size_of(old);
void *new = malloc(new_size);
if (new == NULL)
return NULL;
memcpy(new, old, new_size > old_size ? old_size : new_size);
free(old);
return new;
}
If you have the magic function that can figure out how big an allocation is from the pointer, you can implement realloc yourself like this. malloc pretty much must have this function internally for free to work.
realloc can also do clever things like figuring out that you're reallocating to a smaller size and just free part of your allocation or figure out that you're growing your allocation and there's enough space after to fit it. But you don't need to think about those cases. Thinking that realloc is malloc+memcpy+free will not mislead you except that you need to remember that realloc failing and returning NULL means it didn't do the free.
The realloc implicity frees the input, it may not do anything at all, but you cannot free it after to re-alloced memory. So
char *string1, *string2;
string1 = (char*) malloc(16);
....
string2 = realloc(string1, 8); // this line implicitly frees string1
free(string1); // this is wrong !!!
free(string2);

strcat for dynamic char pointers

I need to write a strcat in C. I tried below things:
char * c_strcat( char * str1, const char * str2)
{
char * ret = (char *) malloc(1 + strlen(str1)+ strlen(str2) );
if(ret!=NULL)
{
strcpy(ret, str1);
strcat(ret, str2);
if(str1 !=NULL) free str1; // If I comment this everything will be fine
return ret;
}
return NULL;
}
int main()
{
char * first = "Testone";
char *second = "appendedfromhere";
first = c_strcat(first,second);
if(second !=NULL) free(second);
// I want to store the result in the same variable
}
It crashed whenever I free the str1 memory in the c_strcat function. If I don't free then the memory allocated for the first will be leaked (if I understood properly).
How to store returned value to same variable (first)?
From section 7.20.3.2 The free function of the C99 standard:
The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if
the argument does not match a pointer earlier returned by the calloc, malloc, or
realloc function, or if the space has been deallocated by a call to free or realloc,
the behavior is undefined.
And str1 (aka first) was not allocated by one of the three dynamic memory allocating functions, causing the crash. Same for second also.
if don't free then the memory allocated for the first will be leaked(if am understood properly).
Memory will be leaked if malloc(), realloc() or calloc() is used and the memory is not free()d at a later point. As the string literal "Testone" is not dynamically allocated it must not be freed.
Note that the pointer NULL check prior to invoking free() is unrequired as free(), as described above, does nothing if the pointer argument is NULL.
Do I cast the result of malloc?
"Testone" & "appendedfromhere" are string literals, constants. They weren't allocated using malloc(), calloc() or realloc(), so you cannot free them.
If you want to store the results to str1 (like strcat does) the memory needed for the concatenated string must be allocated externally. I.e. str1 (first) must be large enough to hold first + second., e.g. by:
char first[100] = "Testone";
Than inside your c_strcat you do not allocate nor free any memory but just write str2 at the end ('\0') into str1.

Allocating memory not working

I'm trying to allocate some memory as unsigned char* however when I do the pointer doesn't seem to have been initialized!
unsigned char* split = (unsigned char*) malloc ((sizeof(unsigned char)*sizeof(unsigned int)));
memset(&split,0,sizeof(int));
if(split==NULL) {
std::cout<<"Unable to allocate memory!\n";
system("pause");
return 1;
}
However every single time I run I get the error message. It seems to happen no matter what data type I use as well!
Your memset call doesn't write to the buffer you've just allocated, the one pointed to by split. It writes to the area of memory where split variable itself stored - as pointed to by &split. Whereupon split becomes NULL.
When you are calling memset(), you are zeroing the memory occupied by the split variable itself, not the memory that split points to (the memory that malloc() allocated). You need to remove the & operator:
unsigned char* split = (unsigned char*) malloc (sizeof(int));
if(split==NULL) {
std::cout<<"Unable to allocate memory!\n";
system("pause");
return 1;
}
memset(split,0,sizeof(int));

Resources