This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 4 years ago.
In the following code, I have two structs.
The first one is book which describes the number of pages of the book using page.
The second one is library which holds all the books using a pointer books, with the parameter num_book which tells the total number of books of the library.
The program can be compiled and run perfectly fine, and the printf result is OK.
But when I added the extra variable (e.g. int x = 1;) as shown in the code. I can still compile the program, but running the executable gives segmentation fault.
I have no idea why it is the case since everything seems to initialized properly. Thanks.
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int page;
} book;
typedef struct {
int num_book;
book *books;
} library;
int main() {
library *my_library;
int n = 5; // number of books in the library
// extra variable not used
// uncomment it gives segmentation fault
// int x = 1;
my_library->num_book = n;
my_library->books = (book *) malloc( (my_library->num_book) * sizeof(book) );
for(int i = 0; i < my_library->num_book; i++){
my_library->books[i].page = i+10;
printf("Book %d\n"
"Number of pages = %d\n",
i, my_library->books[i].page);
}
return 0;
}
Add this line after declaration of my_library
my_library = malloc(sizeof(*my_library));
In
library *my_library;
/* ... */
my_library->num_book = n;
// ^^^^^^^^^^ junk here
my_library has not been assigned (or initialized with) a usable value.
In C, you must allocate memory for your struct manually using malloc.
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int page;
} book;
typedef struct {
int num_book;
book *books;
} library;
int main() {
library *my_library = (library *) malloc(sizeof(library));
int n = 5; // number of books in the library
// extra variable not used
// uncomment it gives segmentation fault
int x = 1;
my_library->num_book = n;
my_library->books = (book *) malloc( (my_library->num_book) * sizeof(book) );
for(int i = 0; i < my_library->num_book; i++){
my_library->books[i].page = i+10;
printf("Book %d\n"
"Number of pages = %d\n",
i, my_library->books[i].page);
}
return 0;
}
Related
This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 2 years ago.
I came across the problem where a dynamic array of structures is properly initialized and filled with data in a function from an included file, but an attempt to access the content of the array causes segmentation faults in the main function even though the pointer was defined globally. Please have a look at the example below:
my_struct.h
typedef struct my_struct {
int one;
int two;
} my_struct_t;
void update_my_struct(my_struct_t*, int);
my_struct.c
#include <stdlib.h>
#include <stdio.h>
#include "my_struct.h"
void
update_my_struct(my_struct_t *my_s, int num)
{
int i;
for (i = 0; i < num; i++ ) {
my_s = realloc(my_s, sizeof(my_struct_t)*(i+1));
my_s[i].one = 1*i;
my_s[i].two = 2*i;
}
printf(" my_s[0] one: %d two: %d\n", my_s[0].one, my_s[0].two);
}
main.c
#include <stdlib.h>
#include <stdio.h>
#include "my_struct.h"
my_struct_t *my_structs;
void
main(void)
{
int i;
update_my_struct(my_structs, 4);
for (i = 0; i < 4; i++)
printf(" %d. one = %d, two = %d\n", i, my_structs[i].one, my_structs[i].two);
free(my_structs);
}
Compile and run:
$ gcc main.c my_struct.c
$ ./a.out
my_s[0] one: 0 two: 0
Segmentation fault (core dumped)
I checked with gdb and the seg fault occurs in main, so it puzzles me how come the dynamic array can be accessed in the included function, but in the main function even though the pointer was declared in main.c. I will appreciate some helpful hints and comments on this issue.
update
Following up on EML's answer I changed the code of the update function to:
void
update_my_struct(my_struct_t *my_s, int num)
{
int i;
for (i = 0; i < num; i++ ) {
if (my_s == NULL)
my_s = (my_struct_t *) malloc(sizeof(my_struct_t));
else
my_s = (my_struct_t *) realloc(my_s, sizeof(my_struct_t)*(i+1));
my_s[i].one = 1*i;
my_s[i].two = 2*i;
}
printf(" my_s[3] one: %d two: %d\n", my_s[3].one, my_s[3].two);
}
Seg fault still occurs:
$ ./a.out
my_s[3] one: 3 two: 6
Segmentation fault (core dumped)
Valgrind did not provide me with any insightful information, here is the snippet of its output:
==5301== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==5301== Command: ./a.out
==5301==
my_s[3] one: 3 two: 6
==5301== Invalid read of size 4
==5301== at 0x40118F: main (in a.out)
==5301== Address 0x4 is not stack'd, malloc'd or (recently) free'd
==5301==
==5301==
==5301== Process terminating with default action of signal 11 (SIGSEGV): dumping core
...
Here is what I implied in my comments. This assumes *my_s is initially NULL, so realloc in that case will act like malloc.
#include <stdlib.h>
#include <stdio.h>
#include "my_struct.h"
void
update_my_struct(my_struct_t **my_s, int num)
{
int i;
*my_s = (my_struct_t *)realloc(*my_s, sizeof(my_struct_t)*num);
for (i = 0; i < num; i++ ) {
(*my_s)[i].one = 1*i;
(*my_s)[i].two = 2*i;
}
printf(" (*my_s)[0] one: %d two: %d\n", (*my_s)[0].one, (*my_s)[0].two);
}
You can then call it like this.
my_struct_t *my_structs = NULL;
...
update_my_struct(&my_structs, 4);
This will work fine for one initialization and the number of structs allocated is kept by the caller. A second call will reallocate to the new number of structs, and reinitialize everything from the beginning.
I omitted realloc return value check for brevity.
And here is the full code as tested on godbolt.
#include <stdlib.h>
#include <stdio.h>
typedef struct my_struct {
int one;
int two;
} my_struct_t;
void
update_my_struct(my_struct_t **my_s, int num)
{
int i;
*my_s = (my_struct_t *)realloc(*my_s, sizeof(my_struct_t)*num);
for (i = 0; i < num; i++ ) {
(*my_s)[i].one = 1*i;
(*my_s)[i].two = 2*i;
}
}
my_struct_t *my_structs = NULL;
int main ()
{
int i;
update_my_struct(&my_structs, 4);
for (int i=0; i<4; i++)
printf(" (*my_s)[%d] one: %d two: %d\n", i, my_structs[i].one, my_structs[i].two);
return 0;
}
Check your realloc docs: the memory must have been previously allocated with with malloc/etc, or the results are undefined.
Your code doesn't really work either - the realloc is inside your for loop, etc.
And try running valgrind - it would have found this problem.
This question already has answers here:
Assignment of function parameter has no effect outside the function
(2 answers)
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 2 years ago.
Don't mind my code writing style. I specifically created this for testing purposes...
Now to the problem:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define EMB 31
#define NAME_MAX 50
struct TRIP {
char TRIP_NAME[EMB];
int TRIP_TIME;
};
struct DATE {
int day;
int month;
int year;
};
struct TRIP_INFORMATION {
char TRIP_NUMBER[EMB];
char EMBARKATION_POINT[EMB];
char SPECIFIC_DROPOFFPOINT[EMB];
char EXIT_DROPOFFPOINT[EMB];
struct DATE TRIP_DATE;
struct TRIP SPECIFIC_TRIP;
};
struct EMBARKATION_CARD{
//struct DATE TRIP_DATE;
char NAME[NAME_MAX];
int ID_NUMBER;
int PRIORITY_NUMBER;
//int TRIP_TIME;
//char EMBARKATION_POINT[EMB];
//char DROPOFFPOINT[EMB];
struct TRIP_INFORMATION TRIP_INFORMATION;
};
This is for the reference of declaration.
int BeginEmbarkationProcess(int *PASSENGER_COUNT, struct EMBARKATION_CARD * PASSENGER_TO_SAVE, int curr_day, int curr_month, int curr_year){
//struct EMBARKATION_CARD * P;
if(*PASSENGER_COUNT>1){
PASSENGER_TO_SAVE = realloc(PASSENGER_TO_SAVE, *PASSENGER_COUNT * sizeof(struct EMBARKATION_CARD));
if(PASSENGER_TO_SAVE == NULL){
puts("PASSENGER_TO_SAVE VARIABLE = HAS NOT ALLOCATED MEMORY");
return -1;
}
}
if(PASSENGER_TO_SAVE==NULL){
puts("PASSENGER TO SAVE POINTER HAS UNABLE TO ALLOCATE MEMORY");
return -1;
}
int x = 0;
for(x=0;x<*PASSENGER_COUNT;x++){
((PASSENGER_TO_SAVE+x))->ID_NUMBER = (x+1)*30;
((PASSENGER_TO_SAVE+x))->PRIORITY_NUMBER = (x+1)*17;
}
for(x=0;x<*PASSENGER_COUNT;x++){
printf("%d %d\n", (PASSENGER_TO_SAVE+x)->ID_NUMBER , (PASSENGER_TO_SAVE+x)->PRIORITY_NUMBER);
}
*PASSENGER_COUNT = *PASSENGER_COUNT + 1;
int r;
printf("ENTER -1 TO TERMINATE THIS LOOP\n");
scanf("%d", &r);
return r;
}
int main(){
//doIt();
struct EMBARKATION_CARD* E = malloc(sizeof(struct EMBARKATION_CARD));
int ct = 1;
int s = BeginEmbarkationProcess(&ct, E, 3, 3, 2020);
while(s!=-1){
s = BeginEmbarkationProcess(&ct, E, 3, 3, 2020);
}
return s;
}
Since I copy pasted this (and removed some commented out lines but eventually got tired of it), this copy pasted code might have some syntax error. Ignore those syntax error please.
The issue is that realloc WILL keep returning NULL.
This prevents me from readjusting it.
Can someone tell me what the hell is going on.
I know I may have made some errors here but I want to learn about it.
Yes I am just a student learning C language.
This idea is to format text info messages bellowing to a structure within a module.
It works like a charm when trying to define the message with (cf module.c):
/*this works*/
module_text3.info_text[0] = "toto[0]";
module_text3.info_text[1] = "toto[1]";
But when using sprintf, I got segmentation fault (cf module.c):
/*this gives segmentation fault*/
for(cpt=0; cpt < 2; cpt++)
{
sprintf(module_text3.info_text[cpt], "info[%u]", cpt);
}
3 different files: main.c, module.h and module.c
/*main.c*/
/*gcc -o test main.c module.c*/
#include <stdio.h>
#include "module.h"
int main(int argc, char **argv)
{
int i;
struct message3 *ptext3 = moduleFcn3();
for (i= 0; i < ptext3->info_nb; i++)
{
printf("ptext3->info_text[%u]: %s\n", i, ptext3->info_text[i]);
}
printf("ptext3->error_text: %s\n", ptext3->error_text);
printf("ptext3->id: %u\n", ptext3->id);
printf("ptext3->info_nb: %u\n", ptext3->info_nb);
printf("ptext3->info_nb_max: %u\n", ptext3->info_nb_max);
return 0;
}
/*------------------------------------------------------*/
/*module.h*/
#define NB_LINE_MAX 10
struct message3
{
char *info_text[NB_LINE_MAX]; /*a few info lines.*/
char *error_text; /*only one line for error.*/
int id;
int info_nb_max;
int info_nb;
};
extern struct message3* moduleFcn3(void);
/*------------------------------------------------------*/
/*module.c*/
#include <stdio.h>
#include "module.h"
/*static is in "Stack".*/
static struct message3 module_text3;
struct message3* moduleFcn3(void)
{
int cpt = 0;
struct message3 *ptext;
/*this gives segmentation fault*/
for(cpt=0; cpt < 2; cpt++)
{
sprintf(module_text3.info_text[cpt], "info[%u]", cpt);
}
/*this works*/
// module_text3.info_text[0] = "toto[0]";
// module_text3.info_text[1] = "toto[1]";
// cpt = 2;
module_text3.error_text = "This is error";
module_text3.id = 4;
module_text3.info_nb_max = NB_LINE_MAX;
module_text3.info_nb = cpt;
ptext = &module_text3;
return ptext;
}
I would appreciate any advises on how to format my information messages (with our without using sprintf).
Thank you,
You have not allocated space for the strings in the info_text field. The simplest thing to do would be to change the struct:
/*module.h*/
#define NB_LINE_MAX 10
#define INFO_MAX 25
struct message3
{
char info_text[NB_LINE_MAX][INFO_MAX]; /*a few info lines.*/
char *error_text; /*only one line for error.*/
int id;
int info_nb_max;
int info_nb;
};
extern struct message3* moduleFcn3(void);
You did not allocate any memory for the info_text strings. You either have to use malloc() first, or if your C library supports it (the GNU one does), use asprintf() instead of sprintf() to have it allocate enough memory to hold the whole output string for you:
for(cpt = 0; cpt < 2; cpt++)
asprintf(&module_text3.info[cpt], "info[%u]", cpt);
Don't forget that you also have to free the memory again at some point.
The reason that the following line works:
module_text3.info_text[0] = "toto[0]";
Is that the compiler ensures the string "toto[0]" is stored in memory somewhere, and you just make the pointer module_text3.info_text[0] point to that string.
I tried many combinations but really nothing worked. It's been long enough so I decided to write this issue.
I just want an array of pointers to structures so I could later easiely sort it by swaping the addresses. I have a function to get data from file and write to array. Unfortunately, it's impossible for me to read this data outside the function.
My last attempt (I deleted file operations as those are not the issue):
Header.h:
#pragma once
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int32_t year;
uint16_t month;
uint16_t day;
} Date;
typedef struct {
char name[16];
Date date;
uint32_t number;
} Player;
size_t readData(Player** players);
Source.c:
#include "Header.h"
size_t readData(Player** players) {
players = NULL;
players = realloc(players, sizeof(Player*) * 1);
players[0] = malloc(sizeof(Player));
strcpy(players[0]->name, "asd");
printf("$ %s\n", players[0]->name);//OK
return 1;
}
int main() {
Player **players = NULL;
uint32_t elemCount, i;
elemCount = readData(players);
printf("> %s", players[0]->name);//BUM - ERROR!
return 0;
}
I'm using Visual Studio Community 2015. I know it's not so much for coding in C but I managed to configure the solution and it doesn't seem to be the thing imo.
I will be very thankful for help. Yet, I'd like to see it as a remake of my code. I tried some other answers to questions on StackOverFlow like this but they didn't help.
If a parameter of a function is not only read and should be an output too, you have to pass a pointer to your data to the function. If your data type is Player** your paramter type has to be Player ***, so the list of players itselfe is able to be changed inside the function.
size_t readData(char* fname, Player*** players) {
// ^ players is a input and output parameter
Player **tempPlayers = *players; // local list of players
tempPlayers = realloc(tempPlayers, sizeof(Player*) * 1);
tempPlayers[0] = malloc(sizeof(Player));
strcpy(tempPlayers[0]->name, "asd");
printf("$ %s\n", tempPlayers[0]->name);//OK
*players = tempPlayers; // write back list of players to paramter
return 1;
}
int main() {
Player **players = NULL;
uint32_t elemCount, i;
char *fileName = NULL;
elemCount = readData(&players);
// ^
printf("> %s", players[0]->name);//BUM - ERROR!
return 0;
}
If you don't want to use *** you can do it like this:
Player* *readData(char* fname, Player** players, size_t *size) {
players = realloc(players, sizeof(Player*) * 1);
players[0] = malloc(sizeof(Player));
strcpy(players[0]->name, "asd");
printf("$ %s\n", players[0]->name);//OK
*size = 1;
return players;
}
players = readData( fileName, players, &elemCount );
You're passing the pointer to the function by value; the original players in main is not changed. This is no different from doing:
#include <stdio.h>
void func(int x)
{
x = 4;
}
int main()
{
int x = 0;
func(x);
printf("%d\n", x); // zero
}
I'm assuming it's the pointers that got you confused, so you should see your mistake now.
To make the modification visible outside of readData, you will need to use three levels of indirection:
size_t readData(Player*** players) {
*players = malloc(sizeof(Player*) * 1);
*(players)[0] = malloc(sizeof(Player));
strcpy((*players)[0]->name, "asd");
printf("$ %s\n", (*players)[0]->name);//OK
return 1;
}
int main() {
Player **players = NULL;
uint32_t elemCount, i;
elemCount = readData(&players);
printf("> %s", players[0]->name); // prints 'asd'
return 0;
}
There is no point using realloc when you know the pointer being passed is always NULL, so I've changed it to malloc instead.
And on a side note: Visual Studio is perfectly suited to C development, and implements parts of C99 and even C11 (historically MSVC was always stuck at C89). You can just use the .c extension for your source files, and this will make the compiler assume the code is C, or you can explicitly set this in the property pages.
parameter passed to readData() must be the address of the caller's pointer 'players'
each of the references in readData() to players must take that into account.
Othewise the caller's pointer 'player' will not be updated.
Then the main() function, call to printf() is trying to output from address 0, resulting in undefiined behaviour, leading to a seg fault event.
in the main() function, if you insert:
printf( "player value; %p\n", (void*)players);
before the current call to printf() you will see the players pointer still contains NULL.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am currently trying to solve a task, which is quite hard for me, a beginner to C, to handle and so i came to this point where I do not know what to do anymore.
My task is to implement polynomials with several functions....
The functions should be clear when you look at the code I think.
My exact problem is that i dont get a compiler error but a Segmentation Fault. I marked where my attempts to debug lead me to. But I have absolutely no clue on what I have to change. I hope someone can help me fix my code.
So here are the three code parts:
Number one: poly.c
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "poly.h"
struct poly_t {
unsigned degree;
int *coeffs;
};
//constructor: heap
poly_t *poly_alloc(unsigned degree){
poly_t *heap_p;
heap_p = malloc(sizeof(*heap_p)+(degree+1)*sizeof(int)); //or malloc(sizeof(*heap_p)*(degree+1)) furthermore not sure if degree or degree +1
}
//free heap
void poly_free(poly_t *p){
int *coeffs = p->coeffs;
free(coeffs);
free(p);
}
void poly_set_coeff(poly_t *p, unsigned deg, int coeff){
p->degree = deg;
p->coeffs += deg;
p->coeffs[deg] = coeff;
//does not work Segmentation Fault not sure what to do
//p->coeffs += deg;
//*p->coeffs = coeff;
printf("%d",*p->coeffs);
}
//different variations
poly_t *poly_linear(poly_t *p, int a1, int a0){
p->degree=1;
*p->coeffs=a1;
p->coeffs++;
*p->coeffs=a0;
p->coeffs--;
}
poly_t *poly_quadratic(poly_t *p, int a2, int a1, int a0){
p->degree=2;
*p->coeffs=a2;
p->coeffs++;
*p->coeffs=a1;
p->coeffs++;
*p->coeffs=a0;
p->coeffs-=2;
}
//evaluate using horner
int poly_eval(poly_t const *p, int x){
int d = p->degree;
int next;
int adr = *p->coeffs;
int *arr = p->coeffs;
int res = arr[d];
for(int i=0; i<=d; i++){
adr+=(d-i);
next = arr[adr];
adr-=(d-i);
res = res*x+next;
}
return res;
}
//constructor : .txt
poly_t *poly_alloc_d(){
//needs to be finished
}
Number Two: main.c
#include <stdlib.h>
#include <stdio.h>
#include "poly.h"
int main(int argc, char** argv){
if(argc<3){
fprintf(stderr, "syntax: %s x coeffs...", argv[0]);
return 1;
}
poly_t *p = poly_alloc(argc-3);
for(int i = 2; i<argc; i++){
int coeff = atoi (argv[i]);
poly_set_coeff(p, i-2, coeff);
}
return 0;//for debugging
int x=atoi(argv[1]);
int y=poly_eval(p,x);
poly_free(p);
printf("%d\n", y);
return 0;
}
And at last my header file:
poly.h
#ifndef POLY_H
#define POLY_H
/* unvollständiger Verbund */
typedef struct poly_t poly_t;
poly_t *poly_alloc(unsigned degree);
void poly_free(poly_t *p);
void poly_set_coeff(poly_t *p, unsigned deg, int coeff);
int poly_eval(poly_t const *p, int x);
#endif /* POLY_H */
I appreciate every help. I hope you can help me sort this out and please be patient with me a newbie to C...
Thanks in advance
You have not allocated or freed memory correctly, and the function didn't even return the pointer! I think you were trying to allocate one block of memory for the struct and the array it contains, but the struct does not contain an array: only a pointer to an array. You have to allocate them separately:
typedef struct {
unsigned degree;
int *coeffs;
} poly_t;
//constructor: heap
poly_t *poly_alloc(unsigned degree){
poly_t *heap_p;
heap_p = malloc(sizeof(*heap_p));
if (heap_p == NULL)
exit (1); // allocation error
heap_p->coeffs = malloc(degree * sizeof(int));
if (heap_p->coeffs == NULL)
exit (1); // allocation error
return heap_p;
}
//free heap
void poly_free(poly_t *p){
free(p->coeffs);
free(p);
}
There are other mistakes too, for example
p->coeffs += deg;
You mustn't play with the allocated memory pointer, you already did it correctly like this
p->coeffs[deg] = coeff;
although you can use an intermediate pointer if you want:
int *ptr = p->coeffs + deg;
*ptr = coeff;