pointer segmentation fault at scanf [duplicate] - c

This question already has answers here:
NULL arg allowed to sscanf?
(6 answers)
Closed 2 years ago.
a Little help?
I'm pretty sure the answer must be something silly, but I cannot see why am I getting a segmentation fault right after my scanf. I've been staring at my piece of code for a long time now:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Student{
int grade, id;
struct Student *next;
}student;
student *initialize(){
return NULL;
}
int main(){
student *init;
student *nxt;
student *actual;
int resp;
init = (student*)malloc(sizeof(student));
init = initialize();
actual = init;
while(1){
printf("type grade:\n");
scanf("%d", &actual->grade);
printf("type id:\n");
scanf("%d", &actual->id);
printf("wanna continue? (1-YES e <other>-NO)\n");
if(resp==1){
actual->next=(student*)malloc(sizeof(student));
nxt=actual->next;
}else
break;
}
actual->next=NULL;
return 0;
}
No big deal, right? There is a struct, I want to scan a value into it. on my terminal, I get:
type grade:
3
Segmentation fault (core dumped)
any ideas?

First you allocate memory for init
init = (student*)malloc(sizeof(student));
but you immediately set init to NULL with the return value of your initialize() function here
init = initialize();
Not only is this a memory leak, but you next set actual to NULL here
actual = init;
Then later in your while loop you dereference actual (which is NULL) in several places such as here
scanf("%d", &actual->grade);
Dereferencing NULL pointers is undefined behaviour and this is a likely source of your error.

Your initialize() function is returning null and you are creating a memory leak. Instead of returning null initialize the data members to reasonable values.

"Thank you! I saw that you should initialize your structure as null on a tutorial, I guess I did it on the wrong order.. Noobs right? haha I'm sorry about the dumb question, you guys are the best"
you are correct, you should initialize to null. But the code you have doesnt do that.
You need to do this
student *initialize(student * st)
{
st->id = 0;
st->grade = 0;
st->next = NULL;
return st;
}
or use calloc instead of malloc to make a student object (calloc clears the memry to 0)
or do
init = malloc ...
memset(init, 0, sizeof(student));

Related

Why does this C program keeps crashing after printing first "ok"? [duplicate]

This question already has answers here:
How to initialize a pointer to a struct in C?
(7 answers)
My linked list results in segmentation fault every time even though I cannot see a flaw
(2 answers)
Closed 10 months ago.
This program keep crashing after printing first 'ok'. I am running it on VS Code using g++ compiler.
#include<stdio.h>
#include<stdlib.h>
struct rod {
char name;
int *list;
int index;
};
int main()
{
int n=3;
struct rod *rodA, *rodB, *rodC;
rodA->name = 'A';
printf("ok");
rodB->name = 'B';
printf("ok");
rodC->name = 'C';
printf("ok");
rodA->list = (int*) calloc(n, sizeof(int));
rodB->list = (int*) calloc(n, sizeof(int));
rodC->list = (int*) calloc(n, sizeof(int));
}
This line declares three pointer variables, but never initializes them.
struct rod *rodA, *rodB, *rodC;
Then this line corrupts memory because you never set the pointers to a valid memory address:
rodA->name = 'A';
After that, the behavior of the program is 'undefined' and eventually will crash.
That is because of memory violation. You create pointers that point to nothing (garbage). One of them seems to point to read-only memory, and when you try to assign something to it, program crashes. Try allocating them like this:
struct rod *rodA = calloc(1, sizeof(struct rod));

Pointers in array of Structures in C [duplicate]

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 5 years ago.
What i intend to achieve with this code is to take a string character from main function, and then assign it to name in structure at a specific index.
Example: It should print for me Name=> Charles Key=> 0
Next line will be Name=> George Key=> 1...and so on. But it rather picks the last name entered and use it for all though my structure is an array of structure. I don't also want to take it direct in the main...like scanf("%s", &node[i].name) because in the real project i am building, i will calculate for i based on the what the user enters. Please help me out. Thanks
#include<stdio.h>
#include<stdlib.h>
typedef struct{
int key;
char *name;
}test;
int main(){
test node[5];
int i;
char see[10];
//for loop for taking string character in see and then assigning name in structure to it
for(i=0; i<5; i++){
printf("Enter name\t");
scanf("%s", &see);
//assigns name in structure index i to see
node[i].name=see;
node[i].key=i;
}
//prints data stored in structure
for(i=0; i<5; i++){
printf("Name=> %s\t\tKey=> %d",node[i].name, node[i].key);
}
return 0;
}
Change as per following...
char *name; ----> char name[10];
scanf("%s", &see); ----> scanf("%s", see);
node[i].name=see; ----> strcpy(node[i].name, see);
You need to malloc space inside the struct and copy the text rather than assigning it. When you assign the pointer you are effectively making the struct's pointer point to the same memory so the next time you read into that memory you overwrite the old value.
Try replacing:
node[i].name = see;
with:
node[i].name = malloc(strlen(see) + 1);
if (node[i].name == NULL)
{
// Handle Malloc error
}
strncpy(node[i].name, see, strlen(see) + 1);

Segmentation fault [duplicate]

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 6 years ago.
What is wrong with this code snippet? i am getting Segmentation fault!
#include<stdio.h>
int main()
{
struct {
char* name;
int age;
} *emp;
char* empname = "Kumar";
int empage = 31;
emp->name = empname;
emp->age = empage;
printf("empname :%s\n",emp->name);
printf("empage :%d",emp->age);
return 0;
}
And how to correct this program to work?
You are not allocating memory for emp. Before using emp, try
emp = malloc(sizeof(*emp));
if you test your code putting in compilation -Wall, the terminal says you that 'emp' is uninitialized therefore you must allocate in dynamic way 'emp' (malloc etc. etc.).
int len_struct = sizeof(*emp);
emp = malloc(len_struct);
PS: This is my advice : i prefer create a struct in global memory (in Data) because i think that this struct you would use in future in the prg.
You need not to use pointer to struct nor printf.
#include<stdio.h>
int main()
{
puts("empname :Kumar");
puts("empage :30");
return 0;
}

Looping problem in C

I am writing a simple program in c so I can understand better the language but I have a strange problem.
As you see from the code below I have only one loop that it exits when I insert 255 as a value. The problem is that when I select the first(insert option) and after I insert a name the program starts something like a looping and gives me all the time the selection screen...
#include<stdio.h>
#include<stdlib.h>
struct student{
char *name;
int id;
};
void insertStudent(void);
struct student * init(void);
int main(){
struct student *p;
int selectionCode=0;
while(selectionCode!=255){
printf("\nInsert students:1");
printf("\nDisplay students:2");
printf("\nExit:255");
printf("\n\nEnter selection:");
scanf("%d",&selectionCode);
p=init();
switch(selectionCode){
case 1:
insertStudent();
//printf("1\n");
break;
case 2:
//printf("2\n");
break;
case 255:
break;
}
}
//p->name="stelios";
//p->id=0;
//printf("Name:%s ID:%d",p->name,p->id);
//free(p);
//p=NULL;
return 0;
}
struct student *init(void)
{
struct student *p;
p=(struct student *)malloc(sizeof(struct student));
return p;
}
void insertStudent(void){
struct student *p;
p=init();
printf("Enter Name:");
scanf("%s",p->name);//return 1;
printf("Enter ID:");
scanf("%d",&p->id);
//printf("test");
}
Part of the problem may be that the code is not allocating memory for the name field in the structure. The init function allocates a new structure but does not initialize the name field. The insertStudent function then uses scanf to read into that uninitialized pointer. That results in writing to "random" memory and can result in any number of problems including an access violation.
Looks like you have a memory leak, I would pass p into insertStudent().
You also have a return 1; in the middle of the insertStudent() call, so it will be returning before finishing its job.
You have "return 1;" after you scan in the name. It looks like logically you should not be returning at that point, since you want to enter in the ID. Also, you declared the function as returning "void" so returning one is an error.
Edit: The real problem is that you never allocated space for the name string.
try to:
struct student *insertStudent(void){
struct student *p;
p=init();
printf("Enter Name:");
scanf("%s",p->name);
printf("Enter ID:");
scanf("%d",&p->id);
//printf("test");
return p;
}
On the main
case 1:
free(p);
p=insertStudent();
//printf("1\n");
On the init you have to allocate space for the name.
What a mess... :-)
You never malloc() a buffer for p->name, but you are filling if with the scanf().
That is corrupting the memory of your program.
Besides... In your functions you are using the variable p and in your main program as well.
This is NOT the same variable, but you seem to assume it is.
Another problem: return 1; after the scanf() aborts the insertStudent() function so "enter ID " is never executed.
It is a void function so it should not return a value, by the way. The compiler has probably issued a warning about that.
There is probably more wrong with it, but this is what I spot after giving it a quick once over.
You need to remove the "return 1;" from insertStudent, otherwise is will no compile.
You should initialize p->name with malloc and change "scanf("%s",p->name);" to "scanf("%s", &p->name);", because you need a pointer to *char.

passing pointer to recursive function in C

I'm just starting on the road the learning C, and ran into some difficulty:
The code listed below is giving me the following error:
Attaching to program: `/workfolder/cocoa/c_stuff/bookshelf/build/Debug/bookshelf', process 1674.
Cannot access memory at address 0xa0df194
Cannot access memory at address 0xa0df194
// code start
#define MAX_NAME_LENGTH 200
#define MAX_AUTHOR_LENGTH 200
#define MAX_DESCRIPTION_LENGTH 1000
#define MAX_PUBLISHER 200
#define MAX_ISBN 50
//structures<
typedef struct {
char title[MAX_NAME_LENGTH];
char author[MAX_AUTHOR_LENGTH];
char ISBN[MAX_ISBN];
char description[MAX_DESCRIPTION_LENGTH];
char publisher[MAX_PUBLISHER];
} Book;
void getUserInput(Book *s[])
{
printf("what is the book's title ?\n");
fgets(s[book_count]->title, MAX_NAME_LENGTH, stdin);
printf("what is the author's name?\n");
fgets(s[book_count]->author, MAX_AUTHOR_LENGTH, stdin);
printf("what is the ISBN?\n");
fgets(s[book_count]->ISBN, MAX_ISBN, stdin);
printf("write a short description\n");
fgets(s[book_count]->description, MAX_DESCRIPTION_LENGTH, stdin);
printf("what is the book's publisher\n");
fgets(s[book_count]->publisher, MAX_PUBLISHER, stdin);
printf("want to add another book ? Y\\N\n");
book_count++;
if(tolower(fgetc(stdin)) == 'y')
{
return getUserInput(s);
}
else
{
return;
}
}
int main (int argc, const char * argv[]) {
// insert code here...
Book *book_shelf[100];
if((book_shelf[0] = (Book *)malloc(sizeof(Book))) == NULL)
{
exit(1);
}
getUserInput(book_shelf);
return 0;
}
The code compiles properly, and the function runs fine the first time (all the questions get asked and the struct receives the data); but when the user types 'y' to add another book, the mem error occurs.
Any ideas where the error is happening?
Thanks in advance!
You've only ever allocated memory for the first book in main - after that it tries to write to the next slot in the array, which doesn't point to an allocated block of memory, giving you a seg-fault. You're going to have to allocate memory for each book you want to read in.
In addition, since C doesn't know how long an array is, you have to pass that information along into function calls. (And I don't see where you're defining book_count.)
You might try something along these lines:
void getUserInput(Book *s[], int *book_count, int max_book_count)
{
if (book_count == max_book_count) return; // If we've filled all the slots, we can't add anymore without causing trouble.
s[book_count] = malloc(sizeof(Book));
..
if(tolower(fgetc(stdin)) == 'y')
{
(*book_count)++;
getUserInput(s, book_count, max_book_count);
}
return;
}
int main (int argc, const char * argv[]) {
// insert code here...
Book *book_shelf[100];
int book_count = 0;
getUserInput(book_shelf, &book_count, 100);
// Make sure to free all the malloc'd data
}
Even better in this situation, would just be using a loop and skipping the whole recursion step.
int main (int argc, const char * argv[]) {
// insert code here...
Book *book_shelf[100];
char response = 'y';
int book_count = 0;
while (book_count < 100 && response == 'y')
{
book_shelf = malloc(sizeof(Book));
response = getUserInput(book_shelf[book_count++]);
}
// make sure to free all the allocated data!
}
char getUserInput(Book *book)
{
// write input straight to book
printf("what is the book's title ?\n");
fgets(book->title, MAX_NAME_LENGTH, stdin);
...
return tolower(fgetc(stdin));
}
Unless I'm reading something wrong, you haven't defined book_count before using it as an array subscript.
Within main, you allocated on the stack an array of 100 pointers to the Book Structure. I believe it was your intent to allocate 100 structures and then pass the address to that block of structures to getUserInput
Change main to:
Book book_shelf[100];
...
getUserInput(book_shelf);
...
EDIT: OOPS Missed the single Book malloc mentioned in the earlier post. That ones Correct for the first book. If you edit as above and eliminate the
if (book_shelf[0]...) check, you'll accomplish your intended results
You allocate just space for the firstbook, not for the others (malloc in main)
I guess there is some code missing, no declaration and initialization of book_count
You should use loops instead of recursion
Use not recursion but loops for this kind of repetition
Recursion is probably overkill for this problem where a simple do { ... } while(user keeps answering yes) would do. However the problem you having is in main with your Book *book_shelf[100]. There are several ways you could solve this problem.
First change it to an array of Book's like samills suggests:
Book book_shelf[100];
and then change your getUserInput to something like this:
getUserInput(Book *book_shelf, int offset, int length) {
if(offset < 0 || offset >= length) {
return;
}
//...
return getUserInput(book_shelf, offset + 1, length)
}
Or you could use your existing code and change you getUserInput function to look something like this and remove the malloc from main:
getUserInput(Book *book_shelf) {
book_shelf[book_count] = (Book*)malloc(sizeof(Book));
// ...
}
props for correct use of the sizeof operator (I see that thing misused so often it makes my eyes bleed).
As in Josh's answer, by adding the following lines to your code should make it work:
book_count++;
if(tolower(fgetc(stdin)) == 'y')
{
if((book_shelf[book_count] = (Book *)malloc(sizeof(Book))) == NULL)
{
printf("Cannot allocate memory for Book");
exit(1);
}
return getUserInput(s);
}
else
{
return;
}
However, I encourage you not to use the recursive function for getting input. Recursive can lead to difficulties in debugging. You may consider using normal loop instead.
Note: I'm assuming the book_count is global variable which has been initialized to 0
thanks a lot for the replies!
I realized that I hadn't malloc-ed enough memory to handle more then one element of the struct array (Exactly what Josh is saying). So essentially:
Book *book_shelf;
if(book_shelf = (Book*)malloc(sizeof(Book)) == NULL)//exit code
so the second time around I would hit a memory issue.
thanks again!
Looks like your still doing it wrong:
Book *book_shelf;
if(book_shelf = (Book*)malloc(sizeof(Book)) == NULL)//exit code
book_shelf is only the size of a pointer. When you do the malloc you only allocate one Book at a time. This is wrong. You need to allocate contiguous memory for an array of Book objects all in one instanciation of an array.
Like
Book book_shelf[100];
not
Book *book_shelf[100];
or using malloc, use your pointer to point to an array instanciated using
100*malloc(sizeof(Book)).
You may get lucky that no other heap memory is allocated in between your malloc(sizeof(Book)) calls and that the memory management system is alocating contiguous memory by default. Also, book_shelf will only point to the last malloced Book structure, not the first one as you indicated you want in your original question.
Josh is also not allocating enough memory at one time. Use a linked list if you want to keep extending elements to the end of your book_shelf one-by-one.
factorial with pointer and recursion
#include<iostream.h>
#include<conio.h>
int show(int *p)
{
int f;
int x=*p;
if(*p==1) //boundry checking for recursion
return 1;
else
f=x*show(&(--*p)); //this code is similar to f=x*show(n-1); with non-pointers
return f;
}
void main()
{
int a=6;
int b=show(&a);
cout<<b;
getch();
}

Resources