I've been struggling with this one for a few hours now and I'm at a loss as to what's happening. This is the code for program.c:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define SPACE 32
#define INITIAL 4
typedef struct {
char *town;
char *country;
} town_t;
typedef struct {
int num_towns, current_size;
town_t **towns_list;
} index_t;
int main(int argc, char *argv[]) {
index_t town_index;
town_index.current_size = INITIAL;
town_index.towns_list = malloc(town_index.current_size * sizeof(*(town_index.towns_list)));
assert(town_index.towns_list != NULL);
printf("Step: %d\n", 1);
town_index.towns_list[0]->town = malloc(4 * sizeof(*(town_index.towns_list[0]->town)));
printf("Step: %d\n", 2);
assert(town_index.towns_list[0]->town != NULL);
return 0;
}
On Linux this is how it runs:
./program
Step: 1
Segmentation fault
but on Windows it prints out
program.exe
Step: 1
Step: 2
as I'd expect, which really isn't helping. For the Linux output, however, clearly the first print statement is being executed but not the second, which would lead me to think that the line between is that one at fault. Particularly, I think doing town_index.towns_list[0] is causing me issues, but I cannot say why.
This is a relatively complex data structure, so maybe I'm getting lost at some point. Basically town_index is meant to be a index struct that contains the current number of towns in towns_list and current_size which reflects the space currently available to save towns. It also contains an array of pointers to town_ts which contain the name and country as strings.
I've tried to use Valgrind, but it's really not helping out much. Here's a Pastebin for those who want to see.
This is a simplified scenario of what I was experiencing in another program, so don't any mind magic numbers and whatnot.
This is on VirtualBox Linux Mint 64-bit.
Unrelated question, if anyone can: How do I get Valgrind to display the precise lines? I see that everywhere else online, but my output just tells me the folder in which the program and function is, which isn't much help.
You initialized town_index.towns_list, but not town_index.towns_list[0], so town_index.towns_list[0]->town is undefined behaviour.
You missed something like
for (int i = 0; i < town_index.current_size; ++i)
town_index.towns_list[i] = malloc(sizeof **town_index.towns_list);
for the second dimension.
town_index.towns_list and town_index.towns_list[0] are not the same. You initialize town_index.towns_list but town_index.towns_list[0] is equal to 0. The crash caused by dereferencing town_index.towns_list[0]
Related
I keep getting segmentation fault, how can I fix that. I tryed more variants but I get segmentation fault everytime when I am using if statements. My code is something similar with this:
#include <stdio.h>
#include <string.h>
int main()
{
int i;
char *sentence[300];
fgets(*sentence,300,stdin);
int length=strlen(*sentence);
for(i=0;i<length;i++){
if(sentence[i]=="a")
printf("qwer");
else if(sentence[i]=="b")
printf("asdf");
else if(sentence[i]=="c")
printf("zxcv");
// ...
}
return 0;
}
The first thing you're doing wrong is this:
char *sentence[300];
It looks like you're trying to create a buffer of 300 characters, but what you're really doing is creating an array of 300 character pointers. Change that to:
char sentence[300];
Then you want to change this:
fgets(*sentence,300,stdin);
to
fgets(sentence,sizeof(sentence),stdin);
Then you want to change
int length=strlen(*sentence);
to
int length=strlen(sentence);
You need to have a good understanding of how strings work in C. If you haven't read a good introductory book for C, start there. C is not something you're going to pick up by just reading random pages on the web and StackOverflow.
I've got a project that involves creating a text game. I'm creating a struct for each player and putting them in an array. I'm then trying to pass in data and then pass by pointer the array to other functions, however I keep on getting segmentation faults (Although on the odd occasion working fine). I've summarised below.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char name[9];
int cardsHeld;
int hand[8];
} Player;
void printNames(Player** playerArray)
{
for (int i = 0; i < 3; i++)
{
fprintf(stdout, "%s\n", playerArray[i]->name);
}
}
void gamesetup()
{
int count;
fprintf(stdout, "How many players will be partaking in 'The Game'? ( 1 - 5)\n");
fscanf(stdin, "%d", &count);
Player** playerArray = (Player**)malloc(sizeof(Player*) * count);
for(int i = 0; i < count; i++)
{
playerArray[i] = (Player*) malloc(sizeof(Player));
fprintf(stdout, "Please enter the name for player %d.\n\n", i + 1);
fscanf(stdin, "%s", playerArray[i]->name);
}
printNames(playerArray);
}
int main(int argc, char** argv)
{
gamesetup();
return 0;
}
My questions are;
Is the fscanf getting the address of the Player.name member? I'm getting confused whether the -> operator should deference the value of the struct member or since its in an array the address?
I'm not sure why it works sometimes but not others. If it works sometimes fundamentally it should be ok. Is the malloc function allocating memory it should not or is the fscanf putting data in the wrong place.
Thank you.
-EDIT-
Changed the code so it is in a complete program that appears to work without seg faults. I think that my issues arise from not freeing the memory before termination is messing it up next time I run it without compiling first. I'm still not sure why fscanf works as in my mind the argument playerArray[i]->name is returning the value, not the address.
I've worked it out where I was confused. Thank you for all your help in the comments.
The member I am accessing in my array is a string of chars so the first member is a pointer. By using fscanf(stdin, "%s",playerArray[i]->name); This deferenced the pointer (an address) so it works. I was getting in a muddle as it was an member of an array of structs. The segfaults were caused by me messing with the code to try and fix what already worked.
EDIT: OK, I hear you guys, I've isolated the part of my code that's giving me problems, compiled it and made sure that it still gave me the same results, here it goes:
Like before, the segfault appears after the first instance of the for loop on
strcpy(replace[j]->utf8, strtok(data, "\t")); Thanks again!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#define max_chars 45
#define max_UTF 5
#define max_ASCII 7
#define max_word_length 30
#define max_line_length 70
#define max_texto_line 5000
typedef struct {
char utf8[max_UTF];
char ascii_seq[max_ASCII];
int count;
} Replac;
void getTable(FILE *f, char inputfile[],Replac **replace){
char data[max_line_length];
int j;
f = fopen( inputfile, "r" );
if (f == NULL) {
fprintf(stderr, "Can't open input file %s!\n",inputfile);
exit(1);
}
fgets(data,sizeof data,f);
for(j=0 ; strcmp(data,"\n") ; fgets(data,sizeof data,f), j++){
if (feof(f)) {
break;
}
strcpy(replace[j]->utf8, strtok(data, "\t"));
strcpy(replace[j]->ascii_seq, strtok(NULL, "\n"));
}
fclose(f);
}
int main( int argc, char *argv[] ){
Replac *replace=malloc(max_chars * sizeof(Replac));
FILE *fpr,*f,*fpw;
int carprocess = 0;
setlocale(LC_ALL,"pt_PT.UTF-8");
setlocale(LC_COLLATE,"pt_PT.UTF-8");
getTable(f,argv[1],&replace);
}
The text file that I'm copying the character from is formated something like this
UTFCHAR \tab asciichar
ex
Á 'A
END EDIT
-#-##-###-####-####+#####+####p
So I'm a beginner using C, and I've tried all I could think of, this seems like a pretty straight forward thing to do, but since I'm having such trouble clearly shows I have some gap in my knowledge...
I wont bother you with the full code since it is working perfectly, it's just that I wanted to do things differently and that's when the trouble started.
In short I'm doing a program that collects a set of chars of UTF8 type, and their ascii replacement, and stores them in a struct such as
typedef struct {
char utf8[max_UTF];
char ascii_seq[mac_ASCII];
} Replac;
then in main I did the malloc like this
Replac *replace=malloc(max_chars * sizeof(Replac));
If my thought process is correct, this would create a block of available memory to which *replace is pointing to the starting address.
Then I made a function that scans a few UTF8 chars and their replacement and stores them in the struct, something like
void getTable(FILE *f, char inputfile[],Replac **replace)
now, following the debugger, it seems that I'm creating new variable replace of the type Replace** that's on a completely different address, but inside that address is stored the value to the original malloced struct that I passed through the param.
After that I do a
strcpy(replace[0]->utf8, something I got from the table);
following the debugger and searching through the memory adresses, I see that the first time I do this, the first position of the malloc struct is indeed filled with the right data.
followed by
strcpy(replace[0]->ascii_seq, corresponding ascii sequence to the previous UTF8 char);
and that fills the next memory position in the memory block.
So I get something like while debugging on my variables watch
address replace = (Replac **) 0xbf8104fc that contains 0x0878a008
address *replace = (Replac *) 0x0878a008 that contains the whole struct
so inside the address 0x0878a008 I get the data of the utf8 char and then at the address 0x0878a00d I get the ascii seq.
The problem in on the next instance of the loop, when it's time to
strcpy(replace[1]->utf8, something I got from the table);
I get a segmentation fault after that instruction.
So what do you guys think? Am I approaching things correctly, and I'm getting screwed over by syntax or something like that, or is it the base of my knowledge flawed?
Thanks, and a late happy holidays!
f = fopen( inputfile, "r" );
...
typedef struct
{
char utf8[max_UTF];
char ascii_seq[max_ASCII];
int count;
} Replac;
...
fgets(data,sizeof data,f);
You are mixing binary and text format.
Depending on the compiler, sizeof(Replac) will be 16. This includes sizeof(int) which is always 4. There may also be padding if size is not a multiple of 4.
If your data is stored as text, then it will be something like this:
ABCDE\tABCDEFG123456\n
Note that the size of integer in decimal format is anywhere between 0 to 10, so the size is not fixed. And there are (or there should be) new line \n characters.
So you don't want to read exactly 16 characters. You want to write and then read 3 lines for each record. Example:
ABCDE\n
ABCDEFG\n
123456\n
If you are reading in binary, then open the file in binary and use fwrite and fread. Example:
f = fopen( inputfile, "rb" );
Replac data;
fread(f, sizeof(data), 1, f);
This all depends on how your file was created. If you are writing the file yourself, then show the code you used for writing the data.
Also, ASCII is a subset of Unicode. A in ASCII has the exact same representation as A in UTF8.
strcpy(replace[j]->utf8, strtok(data, "\t"));
I get a segmentation fault after that instruction.
You just got the dereferencing order wrong. You first subscripted with [j] and then dereferenced with ->, as if we had an array of pointers to Replacs. But we rather have a pointer to (the first element of) an array of Replacs, hence we must dereference the pointer first and subscript thereafter, i. e. instead of
replace[j]->utf8
we have to write
(*replace)[j].utf8
or the equivalent
(*replace+j)->utf8
I'm new to C programming and I couldn't find solution to my problem. Although the code works (I've been able to include it in other program), when it tries to free the memory assigned by calloc(), it returns the following error:
free(): invalid next size (normal):
followd by what appears to be a memory address. I'm using mpc libraries (for arbitrary precision complex numbers). This is the smallest program that repeats the error:
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
#include <mpfr.h>
#include <mpc.h>
int N = 10;
int precision = 512;
int main(void) {
mpc_t *dets2;
dets2 = (mpc_t*)calloc(N-2,sizeof(mpc_t));
for (int i = 0; i<=N-2; i++) {
mpc_init2(dets2[i],512); //initialize all complex numbers
mpc_set_str(dets2[i],"1",0,MPFR_RNDN); //set all the numbers to one
}
free(dets2); //release the memory occupied by those numbers
return 0;
}
Thanks for your help!
Your for loop breaks after i == N-2, but it should break before. The condition in your for loop should be i<N-2 instead of i<=N-2.
So you try to access memory, which is out of bounds. This leads to undefined behaviour, so anything can happen, including a segmentation fault, a free run time error or nothing.
I'm stunned, why does this code give me a segmentation fault?
#include <stdio.h>
#define LIMIT 1500000
typedef struct {
int p;
int a;
int b;
} triplet;
int main(int argc, char **argv) {
int i;
triplet triplets[LIMIT];
for (i = 0; i < LIMIT; i++) {
triplets[i].p = 9; // remove this line and everything works fine
}
printf("%d\n", triplets[15].p);
return 0;
}
EDIT: After changing LIMIT to 150 I no longer get a segmentation fault, it prints random numbers instead.
EDIT2: Now I know what the site name stands for :) I made the array global and everything works fine now.
Stack overflow! Allocating 1500000 records at 12 bytes per record (assuming 4-byte int), requires more than 17 MB of stack space. Make your triplets array global or dynamically allocate it.
As to your edit - shrinking the array will probably stop the stack overflow, but your printf() call will still print uninitialized data - triplets[15].p could be anything at the time you print it out.
When you do
triplet triplets[LIMIT];
you're allocating that on the stack. Which is apparently too big for your system.
If you do
triplet* triplets=(triplet*)malloc(LIMIT*sizeof(triplet));
you'll allocate it on the heap and everything should be fine. Be sure to free the memory when you're done with it
free(triplets);