1

I wrote a function to write the linked list data to a file, when I write main() and the WriteData() in a single file, then it works just fine. But when I write the WriteData() in a different file and include it in main file using a header file, it gives me segmentation fault. Here's my code

abcd.h:

#ifndef _ABCD_H_
#define _ABCD_H_
struct node{
  char word[50];
  char sort[50];
  struct node *next;
}
void WriteData(struct node *head);
void read_data(struct node **head, FILE *fp);
#endif

main.c:

#include"abcd.h"
int main(int argc, char *argv[]) //file is given as command line argument
{
  FILE *fp = fopen(argv[1], "r");
  struct node *head = NULL;
  read_data(&head, fp); //loads the contents of the file to the list
  WriteData(head);
}

writeData.c:

#include"abcd.h"
void WriteData(struct node *head)
{
  FILE *fp = fopen("dictionary.txt", "w");
  if(fp == NULL){
    printf("Error opening file..\n"); 
    return;
  } 
  while(head != NULL){
    fprintf(fp, "\n%s:", head->word);
    fprintf(fp, "%s", head->sort);
    head = head->next;
  } 
  fclose(fp);
  printf("Data saved successfully..\n");
}

readData.c:

#include "abcd.h"
void read_data(struct node **head, FILE *fp)
{
  if(fp == NULL){
    printf("Error opening file..\n");
    return;
  }
  struct node temp;
  temp.next = NULL;
  struct node *hp, *curr;
  hp = *head;
  while(!feof(fp)){
    fscanf(fp, " %[^:]", temp.word);
    fseek(fp, 1, SEEK_CUR);
    fscanf(fp, " %[^\n]", temp.sort);
    struct node *temp2 = (struct node*)malloc(sizeof(struct node));
    if(temp2 == NULL){
      printf("Couldn't make new node by malloc:");
      return;
    }
    *temp2 = temp;
    if(hp == NULL){
      curr = hp = temp2;
    } 
    else
      curr = curr->next = temp2;
  }
  fclose(fp);
  *head = hp;
  printf("Data loaded successfully..\n");
}

Error:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a5cc80 in _IO_vfprintf_internal (s=0x604830, 
     format=<optimized out>, ap=ap@entry=0x7fffffffd928) at vfprintf.c:1632
1632    vfprintf.c: No such file or directory.
EsmaeelE
  • 2,331
  • 6
  • 22
  • 31
pratap
  • 23
  • 1
  • 8
  • I tried to print the list after loading the data from file to check if the data is loaded correctly or not.. The list is ok.. having problem while writing the data to a file – pratap Jun 13 '17 at 19:28
  • 1
    `read_data(&head, fp);` Where and how is head defined ? – Zakir Jun 13 '17 at 19:28
  • it's defined inside `main()` as `struct node *head` and initialized with `NULL` – pratap Jun 13 '17 at 19:30
  • 1
    valgrind will probably help you here, or even just careful stepping through a debugger. – bmargulies Jun 13 '17 at 19:47
  • I new in programming. I tried to use gdb as well as valgrind, but can't figure out where the segmentation fault happening.. – pratap Jun 13 '17 at 19:49
  • @pratap Where's the definition of `read_data`? – dbush Jun 13 '17 at 20:17
  • @dbush I've included it in the question – pratap Jun 13 '17 at 20:23
  • in read_data : please do the malloc of temp2 before the loop; Moreover, you do :*temp2 = temp ; this way of copying is probably not what you want. Copy each element one by one. –  Jun 13 '17 at 20:33
  • 2
    You're using `feof` incorrectly. Also, please see the examples on using `perror` to report error messages on a file open error: https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – William Pursell Jun 13 '17 at 21:11

1 Answers1

-1

I fixed some typo in your code and this is my version:

main.c

#include "hd.h"

int main(int argc, char *argv[]) //file is given as command line argument
{
  FILE *fp = fopen(argv[1], "r");
  struct node *head = NULL;

  //read_data(&head, fp); //loads the contents of the file to the list
 WriteData(head);
}

hd.h

#ifndef _hd_h_
#define _hd_h_
struct node{
  char word[50];
  char sort[50];
  struct node *next;
};

#include <stdio.h>
extern void WriteData(struct node *head);

#endif

write.c

#include "hd.h" 

void WriteData(struct node *head)
{
  FILE *fp = fopen("dictionary.txt", "w");
  if(fp == NULL){
    printf("Error opening file..\n"); 
    return;
  } 
  while(head != NULL){
    fprintf(fp, "\n%s:", head->word);
    fprintf(fp, "%s", head->sort);
    head = head->next;
  } 
  fclose(fp);
  printf("Data saved successfully..\n");
}

Compile with GCC:

gcc -Wall main.c write.c -o prog

You should consider we must compile two .c file, and link them together to make an executable object code (binary file) under the name of main.

Then we can invoke loader program in Unix-like machine to load and execute the program main with typing this command in terminal then hitting the Enter key.

Run

./main

[Edit- ToDo]

Thanks for Basile Starynkevitch for precious comments and show some faults in my post.

  1. Separate Compilation and Linkage process.
  2. Automate them with make file.
  3. Some extra improvement, explanation, documents.
  4. Use different linker program.
  5. Make some improvement on Codes.
EsmaeelE
  • 2,331
  • 6
  • 22
  • 31
  • 1
    every c function is extern by default, even if we don't write `extern` explicitly before the function name http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/ – pratap Jun 13 '17 at 21:43
  • [**Understanding "extern" keyword in C - GeeksforGeeks**](http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/) – David C. Rankin Jun 18 '17 at 05:51
  • Compilation command is wrong, should be `gcc -Wall -g main.c write.c -o prog` and running command should be `./prog` and debugging command would be `gdb ./prog` – Basile Starynkevitch Oct 26 '17 at 12:37
  • @BasileStarynkevitch but this way of compile works for me – EsmaeelE Oct 26 '17 at 12:40
  • But it might not do what you want (no linking step, check by passing also `-v` to your `gcc` command). Read chapter on [invoking GCC](https://gcc.gnu.org/onlinedocs/gcc/Invoking-GCC.html) ... And you certainly want warnings and debug info at first. – Basile Starynkevitch Oct 26 '17 at 12:41
  • @BasileStarynkevitch Thanks for teaching some thing new to me i will correct it, and use in future works, but why you use `-g flag ?` – EsmaeelE Oct 26 '17 at 12:45
  • Because you want to be able to debug. The `-g` flag adds debug information in [DWARF](https://en.wikipedia.org/wiki/DWARF) format. And the `gdb` debugger wants it. – Basile Starynkevitch Oct 26 '17 at 12:46
  • BTW, I downvoted your answer because your compilation command was wrong. I will remove my downvote if you correct the compilation command. You could also recommend learning to use [GNU make](https://www.gnu.org/software/make/manual/html_node/index.html) or some other build automation tool like [ninja](http://ninja-build.org/) – Basile Starynkevitch Oct 26 '17 at 12:47
  • @BasileStarynkevitch If i remove debug flag for simplicity and just only use `gcc -Wall main.c write.c -o prog`, is it still wrong way of compiling two sources. – EsmaeelE Oct 26 '17 at 12:51
  • No. Read the documentation of GCC. You might add `-flto` but that is only useful with optimization flags like `-O`. Of course it is much better to separate compilation and linking and to use a real build automation tool. You could improve your answer by showing some simple `Makefile` and recommend building with `make` – Basile Starynkevitch Oct 26 '17 at 12:56