Segmentation fault while using malloc with char pointers - c

I am new to C and learning structs. I am trying to malloc a char pointer with size 30 but it is giving a segmentation fault(core dump). I searched it on the internet & SO but am not able to resolve this. Any help will be much appreciated.
Probably I am accessing the char* member of the struct incorrectly ?
typedef struct{
int x;
int y;
char *f;
char *l;
}str;
void create_mall();
void create_mall() //Malloc the struct
{
str *p;
p->f = (char*)malloc(sizeof(char)*30); // segmentation fault here
p->l = (char*)malloc(sizeof(char)*30);
printf("Enter the user ID:");
scanf("%d",&p->x);
printf("\nEnter the phone number:");
scanf("%d",&p->y);
printf("\nEnter the First name:");
scanf("%29s",p->f);
printf("\nEnter the Last name:");
scanf("%29s",p->l);
printf("\nEntered values are: %d %d %s %s\n",p->x,p->y,p->f,p->l);
}
int main(void)
{
create_mall();
return 0;
}

Here's your problem:
str *p;
You've declared a pointer to an instance of str, but you haven't initialized it with a value. You either need to move this variable to the stack:
str p;
...or malloc some memory for it first:
str *p = (str*)malloc(sizeof(str));

You never allocated space for the struct itself, only a pointer to it.
Try something like:
str *p = malloc(sizeof(str));

As many people have pointed out, you need to allocate memory for that str struct, before writing the fields of it.
The best way to do so in C is:
p = malloc(sizeof *p);
This has the following advantages:
No cast, since no cast is needed in C and having a cast can hide actual errors.
No duplication of type information, by using the sizeof operator to compute how much storage is needed for the value p points at.
When you then allocate the string space, you can simplify it to:
p->f = malloc(30);
Because:
No cast, for the very same reason.
C guarantees that sizeof (char) is always 1, so using it like you did adds nothing, 1 * 30 is always just 30.
Last, you should always check the return value of malloc() before using it, since it can fail and return NULL.

Check for NULL values in return of malloc() function.
Also str *p; < is not initialised.
initialize p as str *p = malloc(sizeof(str));

The problem lies here.
str *p; ---> Problem Line 1<br>
p->f = (char*)malloc(sizeof(char)*30); ----> Problem Line2
p->l = (char*)malloc(sizeof(char)*30);
You have declared a pointer p of type str.
Problem 1:
You have not initialized this pointer to NULL. Thus, p can point to anything.
Problem 2:
Since p is an uninitialized pointer, p->f can point anywhere which is causing the segfault.
Below is the correct way
str *p = NULL;
p = malloc(sizeof(str));
// Check p for NULL
memset(p, 0, sizeof(str));
Now you have an initialized memory pointed by p. You are now free to use it as you want.

Related

using array of chars and strdup, getting segmentation fault

Suppose i write,
char **p;
p[0] = strdup("hello");
Strdup creates a duplicate string in heap with ending character '\0'; As p is pointer to pointer of char, p[0] = strdup("hello") seems perfectly fine for me. But why am i getting segmentation fault.
Let's look at a simpler example. Suppose you say
int *ip;
ip[0] = 5;
ip is a pointer to one or more ints -- but it's not initialized, so it points nowhere, so ip[0] isn't a valid memory location, so we can't store the value 5 there.
In the same way, when you said
char **p;
p is a pointer that points nowhere. If it did point somewhere, it would point to another pointer. But it doesn't point anywhere, so
p[0] = strdup("hello");
blows up.
To fix this, you need to make p point somewhere, and specifically to memory allocated to hold one or more pointers. There are many ways to do this:
char *q;
p = &q; /* way 1 */
char *a[10];
p = a; /* way 2 */
p = malloc(10 * sizeof(char *)); /* way 3 */
or instead of using a pointer, use an array to start with:
char *p[10]; /* way 4 */
After any of those, p[0] = strdup("hello") should work.
For way 3, we would also need to check that malloc succeeded (that it dd not return a null pointer).
For ways 2 through 4, we could also set p[1] through p[9]. But for way 1, only p[0] is valid.
See also this answer to a different question for more discussion about trying to use uninitialized pointers.
There is declared an uninitialized pointer that has an indeterminate value.
char **p;
so dereferencing the pointer in this expression p[0] (that is equivalent to the expression *p) used in this statement
p[0] = strdup("hello");
invokes undefined behavior because there is an attempt to write to memory using an incorrect pointer value of the expression p[0].
You could write either for example
char *s;
char **p = &s;
p[0] = strdup("hello");
Or
char **p = malloc( sizeof( char * ) );
p[0] = strdup("hello");
That is the pointer to pointer p must point to a valid object. Thus dereferencing the pointer you will get a valid object of the type char * that will be assigned by the value returned by the call of strdup..

Can someone explain why I'm getting segmentation fault 11?

Here is my code:
int main() {
typedef struct {
int recordCount;
char *firstName;
char *secondName;
char *id;
char *email;
}student;
student *students = malloc(sizeof(*students));
int i = 0;
while (students[i].firstName[0] != '.'){
students[i].firstName = (char *)malloc(sizeof(char*));
scanf("%s", students[i].firstName);
i++;
students = realloc(students, sizeof(students) * (i + 1));
}
}
When I run it through a for loop it works, I'm pretty sure it's just something silly going on with my while loop.
malloc returns a block of uninitialized memory. So students[i].firstName is an uninitialized pointer which you attempt to dereference. Reading and dereferencing an uninitialized pointer invokes undefined behavior, which in this case manifests as a crash.
When you do allocate space for the firstName member, you only allocate sizeof(char*) bytes for it which is the size of a pointer, not necessarily the length of a string you would want to read.
Create a buffer to read strings into that's big enough for what you might need, then use strdup to create a copy to assign to the relevant pointer.
student *students = NULL;
int i = 0;
char str[100];
scanf("%99s", str);
while (str[0] != '.'){
students = realloc(students, sizeof(*students) * (i+1));
students[i].firstName = strdup(str);
i++;
scanf("%99s", str);
}
For a start,
students[i].firstName = (char *)malloc(sizeof(char*));
allocates enough space for a character pointer, typically four or eight bytes.
While there are some names that will fit in that (such as Pax or Bob), the vast majority probably won't.
You need to allocate enough space for the largest name (and string terminator), such as with:
#define MAX_NAME_LEN 100
students[i].firstName = malloc(MAX_NAME_LEN + 1);
There are plenty of issues in your code.
When you are using malloc, you actually specify the data type and not the pointer type which is I believe is not your intent here. If you are specifying a pointer type with sizeof, the pointer will point to a memory location having the size of the pointer. This is not what you want in this case.
After the line student *students = malloc ... . The students will point to a memory location which will hold zero values in firstName. You need to use malloc for these. Since you are not doing this you are getting a segmentation fault because you are dereferencing an invalid pointer (pointing to location 0). You are trying to access it first and using malloc afterwards.
If you
student *students = malloc(sizeof(*students));
you are allocating size of one pointer. What you want to do is instead
student *students = malloc(sizeof(students));
and for the same reason, students[i].firstName = (char *)malloc(sizeof(char*)) quite surely do not have enough memory for your name as well, try malloc(sizeof(char)*100) or so.

Array with uninitialized size inside struct

In the program
#include<stdio.h>
struct t {
char a[5];
char b[];
} temp;
int main(){
temp.b[0] = 'c';
temp.b[1] = 'b';
temp.b[2] = '\0';
printf("Size of struct = %lu\n", sizeof(temp));
printf("String is %s\n", temp.b);
printf("Address of temp = %p\n", &temp);
printf("Address of array a = %p\n", &(temp.a));
printf("Address of b = %p\n", &(temp.b));
}
with output
Size of struct = 5
String is cb
Address of temp = 0x601035
Address of array a = 0x601035
Address of b = 0x60103a
In this program, how exactly is array b being allocated? How long is it? Is this some undefined behavior, which is only succeeding in the dummy program as I am not doing anything else. Running into gdb, I can access some memory locations initialized as zero, which makes me suspect that it is allocating some memory.
I do have an api that requires me to format one element of struct as int a[][SIZE], and I am confused about that.
Also, why is sizeof not taking into account at least something from array b. I am not sure if it is taking it as an array or pointer.
The way you use it is undefined behavior. To answer your immediate question, with static or automatic storage (as you use it), this member has a size of 0. So any index will be invalid. It "seems" to work in your experiment, but remember, c doesn't do any bounds checking. In fact, you're doing invalid writes and you're just lucky your example doesn't crash and burn.
Such a member is only allowed as last member of a structure and the reason for this is you can use it with dynamic storage:
struct t *temp = malloc(sizeof(struct t) + 5 * sizeof(char));
will allocate an instance of struct t with temp->b being an array of char of size 5.

Memcpy func take Pointer variable? char *p; char* q; memcpy(p,q,10); will it work?

Memcpy and memcmp function can take a Pointer variable?
char *p;
char* q;
memcpy(p,q,10); //will this work?
memcmp(p,q,10); //will this work?
No, your code as written will not work, since you're passing uninitialized pointers to memcpy() (and memcmp(), but the memcpy() call is enough). This will cause undefined behavior, since you're not allowed to read/write from those "random" locations.
You can fix it by making sure the pointers are valid, for instance:
char buf[10], *p = buf;
const char *q = "hello hello";
memcpy(p, q, 10);
printf("the copying made the buffers %s\n",
memcmp(p, q, 10) == 0 ? "equal" : "different");
Of course p can be replaced by just plain buf above.

String copy(strcpy)

I have the following code.
#include <string.h>
#include <stdio.h>
int main()
{
char * l;
*l = 'c';
*(l+1) = 'g';
*(l+2) = '\0';
char *second;
strcpy(second, l);
printf("string: %s\n", second);
}
When I run it is says:
The output says "Segmentation fault"....any suggestions??
Thanks
l is an uninitialized pointer; you can't dereference it. You should allocate enough space to write its contents (statically (1) or dynamically (2)).
char l[3]; /* (1) */
#include <stdlib.h>
char *l = malloc(3); /* (2) */
It is the same error with strcpy: second is an unitialized pointer, you can't write into it.
You will learn to despise the Segmentation Fault error...
It's usually called when you try to access memory that is not yours. Most common occurrence would be when you try to access an array index that is out of bounds.
char *l just creates a pointer to a char. What you want is a string, which in C is defined as an array of chars. So when you try to access the next location in memory of whatever l is pointing to (which will probably just be garbage), you're going to access memory that isn't yours, thus Segmentation Fault
You could get memory with malloc or point the pointer to an already existing variable.
char word[3];
char *l;
l = word;
Now you can do such assignments:
*l = 'c';
*(l+1) = 'g';
*(l+2) = '\0';
but now that you want to copy it to another pointer, this pointer must be pointing to another string or you should allocate memory for it.
char *pointer_to_second;
char second[3];
pointer_to_second = second;
or if you prefer to get dynamic memory, change the 3 lines above be this one bellow:
char *pointer_to_second = malloc(sizeof(char) * 3);
after that you can do what you wanted:
strcpy(pointer_to_second, l);
But remember, if you are using a C compiler you must declare all variables at the beggining, otherwise you will get an error. If you are using a C++ compiler you won't have to concern about it.
Segmentation fault happens when you try to access a field that doesn't belong to your vector. For example, if you try this:
printf("The value in position 3 of my pointer is %c\n", *(l + 3));
You will probably get an error, because you pointer have 3 positions and you are trying to acess the 4th one.

Resources