C - dynamic memory allocation using double pointer - c

I am allocating some memory in a function name myalloc() and using and freeing it in main().
I am using double pointer to do this, here is the code which works fine,
//Example # 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void myalloc( char ** ptr)
{
*ptr = malloc(255);
strcpy( *ptr, "Hello World");
}
int main()
{
char *ptr = 0;
myalloc( &ptr );
printf("String is %s\n", ptr);
free(ptr);
return 0;
}
But following code does not work and gives segmentation fault.
I think this is another way to use double pointers.
//Example # 2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void myalloc( char ** ptr)
{
*ptr = malloc(255);
strcpy( *ptr, "Hello World");
}
int main()
{
char **ptr = 0;
myalloc( ptr );
printf("String is %s\n", *ptr);
free(*ptr);
return 0;
}
Please clarify me, why it is giving me seg fault in second example.
Note: Language = C, Compiler = GCC 4.5.1, OS = Fedora Core 14
Also, i know that there are some question already been asked related to memory allocation using double pointers, but they don't address this issue, so please don't flag it as repetitive question.

char **ptr = 0;
*ptr = malloc(255);
tries to write the pointer returned by malloc to the address(of type char*) pointed to by ptr. The address turns out to be ... 0, which is not writable memory.
ptr should point to an address you can write to. You can do one of the following:
char *stackPtr; // Pointer on the stack, value irrelevant (gets overwritten)
ptr = &stackPtr;
// or
char **ptr = alloca(sizeof(char*)); // Equivalent to above
// or
char **ptr = malloc(sizeof(char*)); // Allocate memory on the heap
// note that ptr can be 0 if heap allocation fails

char **ptr = 0;
foo( ptr );
You are passing the value that ptr points to. But you havent pointed ptr to anything yet.
*ptr = malloc(255);
Now you are assigning some memory to that "nothing". So this wont work, and will segfault.
Why are you saying that this is another way of using double pointers? I apologise if I am wrong, but I guess you worked with type of program in Turbo-C earlier?

In the second case, you are passing the value of main's ptr, which is 0 (NULL), to myalloc()'s ptr. myalloc() then tries to dereference its null pointer, ptr.

Related

Why am I receiving invalid pointer error when running this code

I am receiving the following error when running this code.
Error in `main': free(): invalid pointer:
My idea is to use a pointer allocated through malloc. This is a sample code.
Please let me know why I am receiving this error.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int c=10;
int* ptr = NULL;
ptr = (int*)malloc(sizeof(int));
if(ptr == NULL)
{
printf("Memory not allocated");
exit(0);
}
ptr = &c;
free(ptr);
ptr=NULL;
}
int c=10;
Variable c allocated on the stack.
ptr = (int*)malloc(sizeof(int));
Assign address of allocated memory on the heap to ptr
ptr = &c;
Assign address of c to ptr.
You have two problems in your code.
Memory Leak. You have lost address of allocated memory since you used reassign of ptr. In this case you don't have any other way to free memory allocated on the heap until program ends.
You can't free memory allocated on the stack with free() function. It's auto variables
So, If you were trying to assign the value of c to the allocated space:
*ptr = c;
Why am I receiving an invalid pointer error?
Because you free a pointer that was not allocated with malloc (or realloc).
You have a memory leak, i.e. you lose a malloced pointer with ptr = &c, which assigns the address of c to ptr, losing the value returned by malloc.
Well to do that you need to allocate for a pointer of pointer like this
#include <stdio.h>
#include <stdlib.h>
int main() {
int c=10;
int** ptr = NULL;
ptr = (int**)malloc(sizeof(int*));
if(ptr == NULL)
{
printf("Memory not allocated");
exit(0);
}
*ptr = &c;
free(ptr);
ptr=NULL;
}
the problem in your case that you are freeing a non dynamic allocated memory and that gives you an error, and even in other cases you should always keep the address of the allocated memory to free it when you no more need it for example
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr1 = (int*)malloc(sizeof(int));
int *ptr2 = (int*)malloc(sizeof(int));
*ptr1 = 5;
*ptr2 = 10;
// this is wrong because now there is no way to free
// the address of the allocated memory to ptr1
ptr1 = ptr2;
free(ptr1);
// this gives an error because ptr2 is already free
free(ptr2);
}
Conclusion:
If you want to allocate to store a pointer, then you need to allocate for a pointer to pointer, so the pointer of the allocated memory stay so you can free that memory when you no longer need it

difference between creating an array "normally" and with malloc

I was messing with C pointers to pointers in functions to learn. I created a string array, and wanted to change it in the function foo with a pointer to pointer. I then print it, just to see.
Problem is: if I create it "normally": char array[] = "yeah", the code doesn't work and I see a bunch of weird characters on the console. But, If I create it with a malloc, it works. I really want to understand the difference.
This works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void foo(char **ptr);
int main(int argc, char *argv[]) {
char *array = malloc(sizeof("yeah")); //I need to malloc here, or it doesn't work. Why ?
strcpy(array, "yeah");
printf("array before : %s \n", array);
char *ptr = array;
char **pt = &ptr;
foo(&array);
printf("array after : %s \n", array);
free(array);
}
void foo(char **ptr) {
char *truc = malloc(sizeof(char) * 20); //I need to malloc here, else it doesn't work. Why ?
strcpy(truc, "then");
*ptr = truc;
}
but this doesn't, it prints nasty characters on the console:
void foo(char **ptr);
int main(int argc, char *argv[]) {
char array[] = "yeah"; //created "normally"
printf("array before : %s \n", array);
char *ptr = array;
char **pt = &ptr;
foo(&array);
printf("array after : %s \n", array);
free(array);
}
void foo(char **ptr) {
char truc = "then";
*ptr = truc;
}
What is the difference between:
char array[] = "yeah";
and
char *array = malloc(sizeof("yeah");
strcpy(array, "yeah");
The Array Way
First thing you should note: The code: char array[] = "yeah"; will work.
Note: if you do this, you do not call free(array) because it is not a pointer to dynamically-allocated memory, and does not need to be dynamically returned to the heap. It exists on the stack. Read on...
But the function foo() here is the problem. When foo() is called, the string truc (which also could be declared char truc[] = "then";) exists in a stack frame, which is a section of program memory, which only exists until foo() returns. If you change array to point to memory within that stack frame, what happens when that function returns? That stack frame becomes undefined, and you're left pointing at junk memory.
If you want to change the contents of the string in array, you could ensure the buffer is long enough, and foo() could strcpy(array, "then") into it. So, you're not changing the pointer itself, just the memory it points to. This isn't what I'd call good software design, but for the sake of an example, it would work for you. Like this:
void foo(char * ptr)
{
strcpy(ptr, "then");
}
So why doesn't it work without malloc() in main()?
When you don't malloc() in main(), array represents, as it suggests, an array. The identifier is not itself a pointer, it is an array; however, it decays to a pointer, or if you will, acts like one. That's why you could pass it off as one, if you wanted, like if you passed it to foo(). Now, if you reference the address of array, like &array, (char*)array, &array, &array[0] are all the same - pointers to the beginning of array. Your foo() is actually writing a memory address to the memory of array, in this case.
What does this do? Well, the technical answer is undefined behavior. But I would guess that it's writing a 32-bit integer (a memory address) to a chunk of memory that used to represent 4 8-bit characters in a string. So now you've corrupted exactly four characters. And, if foo() is using malloc() as you show, also introduced a memory leak.
The neat part of this is that your string is exactly four characters, so this shouldn't corrupt the null terminator '\0' at the end of the string. Let me guess, you see exactly four junk characters?

Why this program is crashing did i wrongly allocated memory

This program is crashing. Please tell me what's wrong with it. When I use an array instead of a pointer like Name[12] in the structure it doesn't crash. I guess there is some problem in dynamic memory allocation. Help please.
#include <stdio.h>
struct struct_tag
{
int number;
char *Name;
} struct_name;
main()
{
struct_name.number = 34;
char *Name = (char *) malloc(sizeof(char));
strcpy(struct_name.Name,"A");
printf("%d", struct_name.number);
}
You're allocating a single character:
char *Name = (char *) malloc(sizeof(char));
And then never using that memory for anything. You meant to allocate memory for struct_name.Name, undoubtedly. But even if you had done so, you're then filling it with two characters ('a' and '\0'):
strcpy(struct_name.Name,"A");
which will cause an entirely different bug.
You want to say:
struct_name.Name = malloc( 2 );
Since (a) you shouldn't cast the result of malloc() and (b) sizeof(char) is always 1 and (c) you need room for the 0 at the end of your string.
For errors:
You are allocating memeory for *Name however you are not allocating
memory for struct_name.Name. So first thing is you need to allocate memory for struct_name.Name
As you already know that you'll be storing "A" in
struct_name.Name you should allocate memory for 2 char.("A" is string i.e 'A' and '\0')
For warnings:
If you want to use strcpy function include string.h in your code.
Also if you are using malloc include stdlib.h in your code.
Try this fixed code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct struct_tag
{
int number;
char *Name;
}struct_name;
int main()
{
struct_name.number = 34;
struct_name.Name = malloc(sizeof(char)*2); // As you will store "A"
strcpy(struct_name.Name,"A");
printf("%d \t", struct_name.number);
printf("%s \n", struct_name.Name);
return 0;
}
first look code carefully.
char *Name = (char *) malloc(sizeof(char));
strcpy(struct_name.Name,"A");
Hare for what you allocated memory (char *Name) and in which you copied string(struct_name.Name)?
here you not allocate memory for struct_name.Name. Also you have allocate memory for one character and you tried to copy two characters.('A' and '\0').
It should be
struct_name.Name = malloc(2);

I am getting Aborted (core dumped) in below code

Hi in my below code for testing realloc() I am getting the error Aborted (Core dumped).
The output of the code is below
$ ./realloc
My Name // <<-- This works
Aborted (core dumped) // <<-- why this error occur?
calling to copyThis() function 1st time gives the correct result and produce no error. In the same way if I call copyThis() for the second time, it make error. I can not understand why is it happening. Can any body point me out where the problem is and what the tweak should I do?
The code is below
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *copyThis(char *str1, const char *str2, size_t size);
int main(void)
{
char *ptr1 = "My Name ";
char *ptr2 = "is Alice";
char *ptr3;
char *ptr4;
ptr3 = copyThis(ptr3, ptr1, strlen(ptr1) + 1); // This works
printf("%s\n", ptr3);
ptr4 = copyThis(ptr4, ptr2, strlen(ptr2) +1); // this line make Aborted (core dumped)
printf("%s\n", ptr4);
}
char *copyThis(char *str1, const char *str2, size_t size)
{
str1 = (char *) realloc(str1, size);
strncat(str1, str2, strlen(str2));
str1[size] = '\0';
return str1;
}
NOTE : Please point me any good tutorial site that can help me catch string operations well in c/
The error is with:
char *ptr3;
char *ptr4;
You should initialize them to NULL:
char *ptr3 = NULL;
char *ptr4 = NULL;
Since ptr3 and ptr4 are not NULL, realloc assumes they were pointers to valid memory. From man realloc:
Unless ptr is NULL, it must have been returned by an earlier call
to malloc(), calloc() or realloc().
Since those pointers are, instead, pointing to random addresses in memory, realloc will get confused when actually using them.
As a more general note, in cases like this it is very helpful to enable additional diagnostics when compiling your code. For example, if you use gcc and if you compile your code with -Wall, the following warnings are emitted:
file.c:19:1: warning: control reaches end of non-void function [-Wreturn-type]
file.c:14:10: warning: ‘ptr3’ is used uninitialized in this function [-Wuninitialized]
file.c:17:10: warning: ‘ptr4’ is used uninitialized in this function [-Wuninitialized]
How to enable those extra warnings depends on what IDE you use for developing, if any; otherwise, if you use the commandline, just add -Wall to the call to gcc.
str1[size] = '\0';
writes beyond the allocated memory, thus your program crashes. You should allocate one more for the 0 character.
The other error is that you call your function fro char* as first argument (ptr3 and ptr4) that are not initialized. This has undefined behavior, anything can happen with such code.
A proper way would be to check if that argument is 0 and then just call malloc with the appropriate size. But for such an approach to work you would have to properly initialize these variables with 0, which you should do, anyhow.
Also, don't cast the return of malloc and relatives, this might hide subtle bugs.
The problem with your code is that you have not initialized the pointers and when you are trying to use realloc it has garbage value and gdb shows :
Breakpoint 1, copyThis (str1=0x7fffffffe060 "\001", str2=0x4007e4 "My Name", size=8) at prog1.c:22
22 str1 = (char *) realloc(str1,size);
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a95b54 in realloc () from /lib/x86_64-linux-gnu/libc.so.6
Due to the garbage address it was failing. So whenever you use pointers always try to initialize them before using.
So the correct program is :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *copyThis(char *str1, const char *str2, size_t size);
int main(void)
{
char *ptr1 = "My Name";
char *ptr2 = "is Alice";
char *ptr3 = NULL;
char *ptr4 = NULL;
ptr3 = copyThis(ptr3, ptr1, sizeof(ptr1) ); // This works
printf("%s\n", ptr3);
ptr4 = copyThis(ptr4, ptr2, sizeof(ptr2) ); // this also works
printf("%s\n", ptr4);
}
char *copyThis(char *str1, const char *str2, size_t size)
{
str1 = (char *) realloc(str1,size);
strncat(str1, str2, strlen(str2));
str1[size] = '\0';
return str1;
}

Issue with freeing an object

I'm currently attempting to learn the C side of C++.
I attempt to malloc a chunk of memory for a char array of 256 and then I assigned it a char* "Hello World!" but when I come to free the object I get an error.
Can anyone please explain to me the error.
#include <exception>
#include <stdexcept>
#include <iostream>
int main()
{
void* charVoidPointer = malloc( sizeof(char) * 256 ) ;
charVoidPointer = "Hello World";
std::cout << (char *)charVoidPointer;
free (charVoidPointer);
}
"Hello World" is statically allocated by the compiler. It is part of the program and exists at some place addressable by the program; call it address 12.
charVoidPointer initially points to some place allocated for you by malloc; call it address 98.
charVoidPointer = "Hello ..." causes charVoidPointer to point to the data in your program; address 12. You lose track of address 98 previously contained in charVoidPointer.
And you can't free memory not allocated by malloc.
To demonstrate more literally what I mean:
void* charVoidPointer = malloc(sizeof(char) * 256);
printf("the address of the memory allocated for us: %p\n", charVoidPointer);
charVoidPointer = "Hello World";
printf("no longer the address allocated for us; free will fail: %p\n",
charVoidPointer);
What you meant was:
strcpy(charVoidPointer, "Hello World");
Edit: Example of addressing memory for other types
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
// an array of 10 int
int *p = (int*)malloc(sizeof(int) * 10);
// setting element 0 using memcpy (works for everything)
int src = 2;
memcpy(p+0, &src, sizeof(int));
// setting element 1 using array subscripts. correctly adjusts for
// size of element BECAUSE p is an int*. We would have to consider
// the size of the underlying data if it were a void*.
p[1] = 3;
// again, the +1 math works because we've given the compiler
// information about the underlying type. void* wouldn't have
// the correct information and the p+1 wouldn't yield the result
// you expect.
printf("%d, %d\n", p[0], *(p+1));
free (p);
}
Experiment; Change the type from int to long, or double, or some complex type.
void* charVoidPointer = malloc( sizeof(char) * 256 ) ;
now charVoidPointer (weird name by the way - if you want chars, use char * and cast the pointer returned from malloc) points at a block of 256 characters. This block is uninitialized, so almost the only valid thing you can do is set them all to some value, or copy something in.
charVoidPointer = "Hello World";
now charVoidPointer points instead at a statically-allocated character array, and you've lost the address returned by malloc. There is no way to get it back, so this is a resource leak.
Your code should look something like:
char *charPointer = (char *)malloc(256);
strcpy(charPointer, "Hello World");
which copies the character array into your allocated block. Or, more concisely, just
char *charPointer = strdup("Hello World");
which will allocate a block just the right size and copy the string in. You still release the block with free.
Use strcpy(charVoidPointer, "Hello World"); because in your example you reassign your pointer.
You're assigning the pointer to the address of the string literal "Hello World", therefore the memory block you malloc'ed is leaked.
You should use
strcpy(charVoidPointer, "Hello World");
instead of the assignment operator.
Even better is to use strncpy(charVoidPointer, "Hello World", 255); to avoid overflowing the array you allocate.

Resources