Segmentation fault causes previous function to not occur - c

Working on a project where I'm creating a linked list from items in a 2d array. The array has been populated correctly, but my method for creating the linked list is causing a segmentation fault. While trying to debug where the fault was occurring, I put a print statement one line above the method call, but the print statement never printed. But, if i commented out the method call, the print statement did print.
main()
{
struct String *list;
char words1[100][1000];
for(int i = 0; i < 100; i++)
words1[i][0] = '\0';
char *words2[100];
for(int i = 0; i < 100; i++)
words2[i] = words1[i];
char ** words = words2;
getStrings(words);
for(int i = 0; i < 100; i++)
{
if(words[i][0] == '\0') break;
printf("%s\n", words[i]);
}
printf("Creating list\n"); //**(RIGHT HERE)** <-----------
//createList(list, words);
//sortStrings(list);
showStrings(list);
return 0;
}
struct String
{
char *s;
struct String *next;
};
void createList(struct String * list, char **words)
{
list = NULL;
struct String *node;
int counter = 0;
while (1)
{
if (words[counter][0] == '\0') break;
printf("Adding: %s", words[counter]);
node = (struct String *) malloc(sizeof(struct String));
node->s = words[counter];
node->next = NULL;
list->next = node;
list = node;
counter++;
}
}
void getStrings(char **s)
{
int count = 0;
for(int i = 0; i < 1000; i++)
{
int ret = scanf("%[^;]", s[i]);
if(ret < 0) break;
count++;
getchar();
}
}
Why would a segmentation fault in the createList() method cause a function that should have been called before it to not execute (or at least not show up)?
Edit: Added getStrings() method to code.

printf function does not write data to standard output immediately, as it might be too slow to do. Instead it might collect data in an internal buffer of stdout object. Once buffer gets full (or sometimes when newline is reached) its content gets "flushed" (written to the underlying file). During normal execution this data is also written before program exits, but because your program gets terminated beforehand, it is not able to empty that buffer, losing data.
You can add fflush(stdout); statement after printf to force data to be written.
Normally when writing to terminal buffer is flushed at \n. I suspect you are writing to a pipe instead (might be your IDE redirects your program output).
You can read more abut file streams here: http://en.cppreference.com/w/cpp/io/c
And about fflush here: http://en.cppreference.com/w/cpp/io/c/fflush
You can also use setvbuf function to manipulate file object buffering: http://en.cppreference.com/w/cpp/io/c/setvbuf

main()
{
/* uninitialized list head must be initialized as NULL */
struct String *list = NULL;
. . .
void createList(struct String * list, char **words)
{
/* Value of list changing only in local scope, list must be a
`struct String **` type. */
list = NULL;
. . .
/* access to field on NULL pointer -> segmentation fault */
list->next = node;

Related

i am trying to read and print one value in a linked list , but my program does not give any output

i am trying to read and print one value in a linked list , but my program does not give any output, i have tryed checking where the program is failing to execute , after the first scanf the code is not printing anything, what might be the reason for that?
code is as followed:
#include<stdlib.h>
#include<stdio.h>
void display();
struct ll{
int val;
struct ll* address;
};
struct ll *new=NULL,*start=NULL,*present=NULL;
int main(void)
{
int num;
scanf("%d",&num);
//reading ll
new=(struct ll*) malloc(sizeof(struct ll));
new->val=num;
new->address=NULL;
if(start==NULL)
{
start=new;
present=new;
}
else
{
present->address=new;
present=new;
}
//calling display func to display the contents of ll
display();
}
void display()
{
present=start;
// displaying.
while (present!=NULL)
{
printf("%d",present->val);
present=present->address;
}
printf("%d",present->val);
}
I have encoded my comments interspersed into your code. I have commented the last statement in function display(), to make it run properly. I have also commented the cast to malloc() (for the given reasons in the code) I have also made some aesthetic changes to make the code more readable. You can add spaces to improve readability of the code, as they don't change the compiler produced code, so please, use enough spaces to make your code more readable (I've done this also to show who it is more readable now):
#include <stdlib.h>
#include <stdio.h>
void display(void);
struct ll {
int val;
struct ll *address;
};
struct ll *new = NULL,
*start = NULL,
*present = NULL;
int main(void)
{
int num;
scanf("%d", &num);
//reading ll
/* Never cast the returned value of malloc() This allows to
* detect if you have properly #include'd the header file and
* avoids other dificult to find errors. malloc() returns a
* void * pointer, so it will be automatically converted to
* any other pointer type without risk. */
new = /* (struct ll*) */ malloc(sizeof(struct ll));
new->val = num;
new->address = NULL;
if(start == NULL)
{
start = new;
present = new;
}
else
{
/* this is never executed, as start == NULL at program
* start. */
present->address = new;
present = new;
}
//calling display func to display the contents of ll
display();
/* while it is not necessary for main() it is normal for a function
* that is defined to return an int value, to return something, so
* I added the following statement: */
return 0;
}
void display(void)
{
present = start;
// displaying.
while (present != NULL)
{
printf("%d",present->val);
present = present->address;
}
/* as you have moved present in a while loop until the while
* condition is false, at this point you must assume the
* condition is false (so present == NULL) and you are trying to
* dereference a NULL pointer below */
/* printf("%d", present->val); */
}
Now your program will run and show the only value (I recommend you to put a \n character at the end of the printf() call, to put the printed data in a line by itself.

c Struct Array, Storing string and its occurrence and writing it to a file

so I'm having a little problem with my struct array not doing what its supposed to. I get no compiler warnings or errors when building the program.
int Array_Size=0;;
int Array_Index=0;
FILE *Writer;
struct WordElement
{
int Count;
char Word[50];
};
struct WordElement *StructPointer; //just a pointer to a structure
int Create_Array(int Size){
StructPointer = (struct WordElement *) malloc(Size * sizeof(StructPointer));
Array_Size = Size;
return 0;
}
int Add_To_Array(char Word[50]){
int Word_Found=0;
for(int i=0; i <= Array_Size && Word_Found!=1; i++)
{
if(strcmp(StructPointer[i].Word, Word)) // This should only run if the word exists in struct array
{
StructPointer[i].Count++;
Word_Found=1;
}
}
if(Word_Found==0) // if the above if statement doesnt evualate, this should run
{
strcpy(StructPointer[Array_Index].Word, Word); //copying the word passed by the main function to the struct array at a specific index
printf("WORD: %s\n", StructPointer[Array_Index].Word); // printing it just to make sure it got copied correctly
Array_Index++;
}
return 0;
}
int Print_All(char File_Name[50])
{
Writer = fopen(File_Name, "w");
printf("Printing starts now: \n");
for(int i=0; i < Array_Size; i++)
{
fprintf(Writer, "%s\t\t%d\n",StructPointer[i].Word, StructPointer[i].Count);
}
free(StructPointer);
return 0;
}
These functions get called from a different file, The Add_To_Array is called when the program reads a new word form the text file. That function is supposed to check if the word already exists in the struct array and if it does, it should just increment the counter. If it doesn't, then it adds it.
The Print_All function is called after all the words have been stored in the struct array. Its supposed to loop through them and print each word and their occurrence. In the text file, there are 2 of every words but my program outputs:
this 13762753
document -1772785369
contains 1129268256
two 6619253
of 5701679
every 5570645
word 3342389
doccontains 5374021
I don't know what to make of this as im really new to C programming... It's probably worth mentioning the if(Word_Foun==0) doesn't execute
StructPointer = malloc(Size * sizeof(*StructPointer));
This will be the correct allocation. Otherwise you will have erroneous behavior in your code. Also check the return value of malloc.
StructPointer = malloc(Size * sizeof(*StructPointer));
if(NULL == StructPointer){
perror("malloc failure");
exit(EXIT_FAILURE);
}
You are allocating for struct WordElement not a for a pointer to it. You already have a pointer to struct WordElement all that you needed was memory for a struct WordElement.
Also in the loop you are accessing array index out of bound
for(int i=0; i <= Array_Size && Word_Found!=1; i++)
^^^
It will be i < Array_Size.
In case match occurs you want to set the variable Word_found to 1.
if(strcmp(StructPointer[i].Word, Word) == 0){
/* it macthed */
}
Also Writer = fopen(File_Name, "w"); you should check the return value of fopen.
if(Writer == NULL){
fprintf(stderr,"Error in file opening");
exit(EXIT_FAILURE);
}
Also when you are increasing the Array_index place a check whether it might access the array index out of bound.
The more global variable you use for achieving a small task would make it more difficult to track down a bug. It is always problematic because the places from which data might change is scattered - making it difficult to manage.

Stack smashing detected, on Eustis

When I compile and run this program on Windows/Eustis I am not getting any errors or warnings.
The basic function of the program is to read in an input text file(source code) and strip out C-style comments /*........*/ to a file cleaninput.txt.
It works on Windows. However, when run on Eusis I get this:
gcc -o out.x a2.c
./out.x
*** stack smashing detected ***: ./out.x terminated
Aborted
I have tried compiling with the command
gcc -fno-stack-protector -o out.x a2.c
./out.x
*** Error in './out.x': double free or corruption (out): 0x09670440 ***
Aborted
Is there a program or utility I can use to figure this out?
#include<stdlib.h>
#include<stdio.h>
#include <string.h>
#define MAX_DEC_LENGHT 11
#define MAX_INTEGER 99999
#define MAX_LINE_WIDTH 100 //used in the struct below defines how wide a instruction can be per line
FILE *fp;
typedef struct input{
char line[MAX_LINE_WIDTH];
struct input *next;
}input;
void scanFile();
struct input *Push(struct input *temp2, char Buff[MAX_LINE_WIDTH]);
void printClean(struct input *temp);
int Get_No_Lines();
void freeme(struct input* ptr);
const char *strip_comments(char input[MAX_LINE_WIDTH]);
int main(){
int x = Get_No_Lines();
scanFile(x); //will read in the input and produce cleaninput.txt, get_no_lines is used to tell the program later how long the input text file is
return(0);
}
/*
Take in an integer N, which represents how many lines there are in the text file, which is used in scanning into a linked list of each line
calls for the print clean input function
Currently not returning anything
*/
void scanFile(int n){
fp = fopen("input.txt", "r");
struct input*temp = NULL;
int i;
for(i=0;i<n;i++){
char Buff[MAX_LINE_WIDTH];
fgets(Buff,MAX_LINE_WIDTH,fp); //fgets is by far the easiest solution i found to scanning in line by line, the linked list is there for unlimited input lenght
temp = Push(temp,Buff); //push the value of fgets onto the linked list
}
printClean(temp);
freeme(temp); //at this point we call the printClean input function
fclose(fp);
}
/*
Take in the the pointer to a linked list, and place the value buff into the structs line segment,
Basic function is linked list push to end
*/
struct input *Push(struct input *temp2, char Buff[MAX_LINE_WIDTH]){
struct input *temp=(struct input*)malloc(sizeof(struct input));
struct input *current = temp2;
strcpy(temp->line,Buff);
temp->next= NULL;
if(temp2==NULL){
return(temp); //base case if null
}
while(current->next!=NULL){
current = current->next; //insert to back of list
}
current->next = temp; //link the new node
return(temp2);
}
/*
The main driver function for stripping the comments out of the input text file,
calls the strip_comments function and places the result back into the struct, then prints to the file stream
currently not returing anythig, shouldnt need to, will be checked later -MM
*/
void printClean(struct input *temp){
fp = fopen("cleaninput.txt", "w");
while(temp!=NULL){
char t[MAX_LINE_WIDTH];
strcpy(t,strip_comments(temp->line)); //copy the contents of strip_comments into t, and then copy the contents of t into temp->line
strcpy(temp->line, t); //yeah im not sure why i need to strcpy's but it wouldnt work without them \_(?)_/¯
fputs(temp->line, fp);
temp=temp->next;
}
fclose(fp);
}
const char *strip_comments(char input[MAX_LINE_WIDTH]){
char output[100];
int i=0;
int x =0;
int inComment = 0; // a boolean variable to let the case statment change behavior in the while loop
while(i<=MAX_LINE_WIDTH){
if(inComment==1){
if(input[i]=='*' && input[i+1]=='/'){
inComment=0;
i++; //end the comment, and increment the counter up two to clear hte comment
i++;
}
}
if(inComment==0){
if(input[i]=='/'&& input[i+1]=='*'){ //condtion to enter the comment switch
inComment=1;
}else{
output[x] = input[i]; //if not in the comment and last check was not in comment push the value of input[i] to output[x] increment x
x++;
}
}
i++;
}
char *rtn = output;
return(rtn); //return the input free of comments, currently cannot handle multi_line comments
}
/*
Used for the scanning function, its sole purpose is to let the program know how many lines there are in the input text file
*/
int Get_No_Lines(){
fp = fopen("input.txt", "r");
int ch, number_of_lines = 0;
do
{
ch = fgetc(fp);
if(ch == '\n')
number_of_lines++; //if the scanner gets to a \n charecter increment
} while (ch != EOF);
if(ch != '\n' && number_of_lines != 0) // needs to be checked, method was adopted from the internet
number_of_lines++;
if(number_of_lines==0){ //i added this case in when we get a one line input that the user has not hit the /n or enter key
number_of_lines =1;
}
fclose(fp);
return(number_of_lines);
}
void freeme(struct input* ptr){
struct input *temp;
while(ptr!=NULL){
temp=ptr->next;
strcpy(ptr->line,"");
free(ptr);
ptr=temp;
}
}
You are returning a pointer to the local variable char output[100];, which invokes undefined behavior. Returning a pointer to a local variable is always a severe bug.
Instead, pass the output buffer as a parameter to the function and leave the allocation to the caller.
Can a local variable be accessed outside its scope?

How to set all values to NULL struct array within a struct array in C

Basically I have two structs and I want to make an array of A structs, and within each A struct I want an array of 50 B structs. So I assume that we will use double pointers.
struct A{
char* a_word;
struct B** b_list;
};
struct B{
char* b_word;
int b_value;
};
When call initialize function I initialize the structs like this. My goal is to set all the values to NULL when I allocate memory.
struct Word** initialize()
{
int k;
int i;
struct A** A_list = calloc(BUFFSIZE, sizeof(struct A*));
for(k =0; k < BUFFSIZE; k++)
{
A_list[k] = calloc (1, sizeof(struct A));
A_list[k]-> b_list = calloc(50, sizeof(struct B*));
for(i = 0; i < 50; i++)
{
A_list[k]->b_list[i] = calloc(1, sizeof(struct B));
}
}
return hashTable;
}
after initializing all these values I am able to do. . .
if(A[43]->a_word == NULL) //43 unallocated value
{
printf("This is null\n");
//program prints this statement - good
//program knows that this value is NULL
}
But I also want . .
if(A_list[44]->b_list[0] == NULL)
{
printf("This is also null");
//This should be printed but nothing happens
}
For some reason not matter if I set the above if statement to == NULL or != NULL the program outputs absolutely nothing from that if statement. What is going on in memory and how can I allocate everything correctly, and so the value is set to NULL as a default and so I can input a value?
EDIT: Also whenever try to do A_list[value1]->b_list[value2] = strdup("string"); I get a segmentation error, this most likely stems from the same problem.
As mentioned already by WhozCraig in a comment to the question, this code
for(i = 0; i < 50; i++)
{
A_list[k]->b_list[i] = calloc(1, sizeof(struct B));
initialises the first 50 elements of b_list to point to valid memory, that is to be non 0, assuming calloc() never fails. Being that optimistic you better test for those elements being != NULL.
... if I set the above if statement to == NULL or != NULL the program outputs absolutely nothing
The code does not seem to flush stdout here:
if(A_list[44]->b_list[0] == NULL)
{
printf("This is also null");
Change this by adding a final \n:
if(A_list[44]->b_list[0] != NULL)
{
printf("This isn't null\n");
As stdout is line buffered by default, all content will be flushed if a new-line is detected.

Segmentation Fault(core dumped) - Structure;

So I have the following question:
I have this struct ListAut
struct ListAut{
char* biggestn;
int sizeof_biggestn;
int total_len;
struct node* avl;
};
Its typedef is as it follows:
typedef struct ListAut *IndexOfAuts;
IndexOfAuts *newIndexOfAuts()
{
int i;
IndexOfAuts *ioa = malloc(27 * sizeof(struct ListAut));
for (i = 0; i < 27; i++)
{
ioa[i]->biggestn = "";
ioa[i]->sizeof_biggestn = 0;
ioa[i]->total_len = 0;
ioa[i]->avl = NULL;
}
return ioa;
}
void insertName(IndexOfAuts * ioa, char *nome)
{
char *aux = malloc(sizeof(nome));
aux = trim(nome);
int index = getIndexOfLetter(aux);
if (nameLen(aux) > getSizeOfLongName(ioa[index]))
{
strcpy(ioa[index]->biggestn, aux);
ioa[index]->sizeof_biggestn = nameLen(aux);
}
ioa[index]->total_len += nameLen(aux);
insert(ioa[index]->avl, aux);
}
This is an important part of a module I need for a project, and on its main it's Seg Faulting. I suspect it's on the creation of an "object" newIndexOfAuts(),
The idea of this module is to have an array of 27 pointers to those structures, one to each letter and another to the special characters;
Now I'm just confused because it might be from the problem above or from a module loader I made:
void loadModules(char *filename, IndexOfAuts * ioa, StatTable st)
{
char *nameofile = malloc(20);
strcpy(nameofile, filename);
FILE *file = fopen(nameofile, "r");
if (file != NULL)
{
int counter, ano;
char *buff, *field, *auxil;
buff = malloc(1024);
field = malloc(200);
auxil = malloc(200);
while (fgets(buff, 1024, file))
{
counter = 0;
field = strtok(buff, ",");
printf("inserting 1st name\n");
insertName(ioa, field);
counter++;
while (!atoi(field))
{
if ((auxil = strtok(NULL, ",")) != NULL)
{
counter++;
field = auxil;
insertName(ioa, field);
}
}
ano = atoi(field);
incPub(st, ano, counter - 1);
}
fclose(file);
}
}
When i run this in main that has the following lines:
printf("Creating Stat Table");
StatTable st=newStatTable();\\This Line is correct, i checked it,i hope
printf("Creating index");
IndexOfAuts* ioa=newIndexOfAuts();
printf("Loading Modules");
loadModules(filename,ioa,st);
Those prints were for me to see where was the cause of the seg fault, but the last line printed was the "Creating Index".
There are several cases of undefined behavior and one memory leak (and a possible case of undefined behavior too):
You have this initialization ioa[i]->biggestn=""; It make the biggestn member point to a constant array of one character (the '\0' character). You then do strcpy(ioa[index]->biggestn,aux); which will write over a constant character, and then go outside of the array writing into unknown memory.
You have this: char* aux=malloc(sizeof(nome)); That allocates only 4 or 8 bytes, which the size of the pointer and not what the pointer points to. Use strlen to get the length of a string.
For the above allocation you also need to allocate a byte extra, as strlen only returns the length of the string without the terminator.
You have aux=trim(nome); This overwrites the pointer you just allocated, leading to a memory leak.
The above call might also lead to undefined behavior if you return a pointer to a local variable or array.
There are probably other problematic lines, these were just the ones I found on a quick glance.
And a general tip: Learn to use a debugger! The debugger is a programmers best tool next to the compiler. If you run your program in a debugger, the debugger will stop at the location of the crash, and let you examine (and also walk up) the function call stack, as well as let you examine values of variables.

Resources