C - malloc and structures, segmentation fault - c

im trying to make program that stores person's last name and name in a structure that is dynamically allocated and then prints it in terminal. For now i have got "segmentation fault" error after inputing the last name in terminal. How do i make it work? Thanks in advance!
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person{
char *last_name;
char *name;
};
struct person *p_person;
int main(void)
{
p_person=malloc(sizeof(struct person));
scanf("%s", p_person->last_name);
scanf("%s", p_person->name);
puts(p_person->last_name);
free(p_person);
return 0;
}

p_person->last_name doesn't point to anywhere. You were accessing memory that you are not even permitted to. You invoke undefined behavior accessing it. Solution would be to allocate some memory dynamically or use char last_name[MAXLEN]; in structure.
Solution 1:
struct person{
char last_name[50];
char name[50];
};
Solution 2:
p_person->last_name = malloc(50);
if( p_person->last_name == NULL){
fprintf(stderr,"error in malloc");
exit(1);
}
In the solution-2,
You should do the same thing for name also.
Free the dynamically allocated memory when you are done working with it.
scanf("%49s", p_person->last_name) One less than the buffer size. When scanf() is finished parsing into a string, it appends NUL terminating character automatically.

Related

Dynamically expanding C code without using realloc

I need to put the names separated by commas from the text into struct that expands dynamically, but I am prohibited from using realloc ().I'm getting a core dumped error in this code. What is the error in this code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct movie{
double budget;
int genre;
char* name;
double score;
int year;
};
void recorder_function(struct movie *movies){
FILE*fp;
fp=fopen("Movies.txt","r");
struct movie *p;
int i,n=0;
char line[1000];
char temp_budget[50];
char temp_name[50];
char temp_genre[50];
while (!feof(fp)) {
fgets(line,1000,fp);
sscanf(line,"%50[^,],%50[^,],%50[^,]",temp_budget,temp_genre,temp_name);
//I open the fields in this section
movies=(struct movie *)calloc(n+1,sizeof(struct movie));
p=(struct movie *)calloc(n+1,sizeof(struct movie));
p[n].name=(char*)malloc(sizeof(char)*(strlen(temp_name)+1));
movies[n].name=(char*)malloc(sizeof(char)*(strlen(temp_name)+1));
for(i=0;i<n;i++)
movies[i]=p[i];
strcpy(movies[n].name,temp_name);
free(p);
p=movies;
n++;
}
for(i=0;i<n;i++)
printf("%s\n",movies[i].name);
}
int main(){
int choice;
struct movie *movies;
recorder_function(movies);
}
It is a bad idea to overwrite the pointer movie by newly allocated clean buffer.
Instead of that, you should
Allocate new buffer only for p.
Put the new element to p[n]
Put existing elements movie[0], ... , movie[n-1] to p[0], ... , p[n-1]
Free the old buffer movie
Assign the new buffer p to movie
Don't forget to initialize movie not to cause troubles at the first freeing.
Also while (!feof(fp)) is wrong and you should check if readings are successful after trying to read and before using what are read.
One more important point is that you should make sure that fopen() succeeded. Passing NULL, which fopen() returns on failure`, to other file manipulation functions may cause troubles.
Another point is that your arrays used for sscanf() outputs should have one more elements for the terminating null-character.
Yet another point is that casting results of malloc() family is considered as a bad practice.
Try this:
void recorder_function(struct movie *movies){
FILE*fp;
fp=fopen("Movies.txt","r");
if(fp==NULL){
fputs("file open error\n", stderr);
return;
}
struct movie *p;
int i,n=0;
char line[1000];
char temp_budget[51];
char temp_name[51];
char temp_genre[51];
movies=NULL;
while (fgets(line,1000,fp)) {
sscanf(line,"%50[^,],%50[^,],%50[^,]",temp_budget,temp_genre,temp_name);
//I open the fields in this section
p=calloc(n+1,sizeof(struct movie));
p[n].name=malloc(sizeof(char)*(strlen(temp_name)+1));
strcpy(p[n].name,temp_name);
for(i=0;i<n;i++){
p[i]=movies[i];
}
free(movies);
movies=p;
n++;
}
for(i=0;i<n;i++){
printf("%s\n",movies[i].name);
}
}
The next stage will be fixing the weird usage of the argument movie. Arguments in C are copies of what are passed, and modifications of arguments in callee functions won't affect what are passed in caller. Your choice is:
Remove the argument movies and convert that to a local variable.
Have recorder_function take a pointer to struct movie* (struct movie**) and have it use the pointer to modify what caller specifies. (You also have to change the statement to call the function to pass a pointer in this case)

How to modify a string inside a struct in C?

I am trying to modify a field inside a struct. I have no trouble doing this with other types (i.e. int, float etc.) but char * is giving me problems. I think I have to do something like:
typedef struct{
char *string_field;
} struct_name;
struct_name *struct_name1;
struct_name1 = (struct_name *) malloc(sizeof(struct_name));
strcpy(struct_name1->string_field, new_string);
printf("New string: %s\n", struct_name1->string_field);
But this gives me a segmentation fault. What reason do you think I would get this problem for? Initially, I thought maybe the char *string_field was not big enough to copy to, but I changed the size of it manually to be of size 100 (more than enough) and I still get this problem.
You reserve memory for your struct, which comprises a pointer to a string, but not the space for a string's content. Reserve memory for the string content and let your struct's pointer point to it; then you can copy newstring's content into that memory:
struct_name1->string_field = malloc(strlen(new_string)+1);
strcpy(struct_name1->string_field, new_string);
Allocate memory for the structure as well as for the string.
In example below there is a room for 63 characters in the string.
Remember to free the allocated memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *string_field;
} struct_name;
int main()
{
struct_name *struct_name1;
struct_name1 = malloc(sizeof(struct_name));
struct_name1->string_field = malloc(64*sizeof(char));
strcpy(struct_name1->string_field, "new_string");
printf("New string: %s\n", struct_name1->string_field);
free(struct_name1->string_field);
free(struct_name1);
return 0;
}
OUTPUT:
New string: new_string

Segmentation fault on getenv C?

So what helps me when coding is collaberating everything i've learned into one random project. To better help me and understand when coding. I learnt about getenv a while back and was testing it. Worked fine until I went back to work on learning c and opened the project again...
#include <stdio.h>
#include <strings.h>
#include <windows.h>
#include <stdlib.h>
struct envvariabl3s
{
char *userprofile;
char *systemroot;
};
void loginscreen(void)
{
int testbit = 4000000000;
struct envvariabl3s *envariable;
char *memtes;
printf("\nWelcome to the login screen...\n");
memtes = malloc(20 * sizeof(char));
if(memtes == 0)
{
printf("Error: Not enough memory!");
}
strcpy(memtes, "Herp De Derp");
printf("\nDynamically allocated memory is %s", memtes);
free(memtes);
envariable->userprofile = getenv("USERPROFILE"); //SEGFAULT HERE
envariable->systemroot = getenv("SystemRoot");
printf("\nUserProfile is: %s", envariable->userprofile);
printf("\nSystem Root is: %s", envariable->systemroot);
printf("%d", sizeof(testbit));
}
Envvariable is a pointer to a structure, but you never created a struct for it to point to. It just points to random memory, and assigning into the struct that isn't there causes the crash. You need an actual struct, perhaps allocated using malloc(), for the pointer to point to.

there is a runtime error in this file handling code

This is a simple code to store a person's name and number in a file.the problem occurs when i also want to include the person's contact number.the error occurs after the contact number is scanned.
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *fp;//file pointer
char *name,*number;
char filename[]="testfile.txt";//file to be created
fp=fopen(filename,"w");
if(fp==NULL)
{
printf("\nerror\n");
exit(1);
}
fprintf(stdout,"Please enter a name:\t");
fscanf(stdin,"%s",name);
fprintf(fp,"%s",name);
fprintf(stdout,"Enter contact number:\t");
fscanf(stdin,"%s",number);
fprintf(fp,"%s",number);
fclose(fp);
}
you did not malloc() the memory for name and number!
Here is an extract of your code:
char *name;
fscanf(stdin,"%s",name);
name is a pointer to a char (or the first char of a string) but you didn't initialized it's value so it points anywhere.
The second line with fscanf read a word and write it in memory at the address pointed by name. So, basically, fscanf will try to write somewhere it will probably won't be able to write.
There are 2 solutions:
either you change char *name to char name[MAXNAME] (where MAXNAME is a constant value)
either you do a malloc: char *name = malloc(MAXNAME)
The same for number.
Allocate memory for pointers name and number
name = malloc(sizeof(char) * num_elements);
number = malloc(sizeof(char) * num_elements);

segmentation fault in C

I am trying to write this code, but it gives me segmentation fault after running the program, could you please help to sort it out?
#include <stdio.h>
#include <string.h>
typedef struct{
int salary;
char* name;
} employee ;
int main(){
employee p[2];
int i;
for(i=0;i<2; i++){
printf("enter sal ");
scanf("%d", &p[i].salary);
printf("enter name ");
scanf("%s", &p[i].name);
}
for(i=0;i<2; i++){
printf("p %d",p[i].salary);
printf("p %s",p[i].name);
}
return 0;
}
You need to allocate memory for the name field: p[i].name = (char*)malloc(MAX_NAME_LEN)
Also, the scanf("%s", &p[i].name) should read scanf("%s", p[i].name).
The structure field name is just a wild character pointer.
char* name;
you are reading the user input as:
scanf("%s", &p[i].name);
into the memory pointed by name which could be anywhere.
To fix this you need to dynamically allocate memory pointed to by name or you can change name to a char array of size one greater than the max length of the name possible.
char name[MAX];
You don't need the & operator when scanf'ing to pointer. And you need to malloc p[i].name
scanf("%s", p[i].name);
You are not allocating memory for char* name. change your data structure to
typedef struct
{
int salary;
char name[50];
}
or allocate memory using malloc
You forgot to allocate memory for p[i].name.
You have to reserve memory for the name member of each instance of employee:
p[i].name = (char*)malloc(expected_max_size);
just before the scanf for that variable. Declaring a pointer to char char* does not assign memory for the actual string pointed to, but just for the pointer itself, and in your example it is not initialized. By using malloc you reserve a piece of memory and makes the pointer point to it. You have to be careful with bounds checking, because you have to reserve the memory beforehand, enough to hold what the user is writing.
You need to allocate memory for the "name" string in your structure. Do this using malloc() or by declaring name as an array of a given size (char name[SIZE]).

Resources