LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-13-2023, 12:22 AM   #1
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,144

Rep: Reputation: 392Reputation: 392Reputation: 392Reputation: 392
Getting a segfault. Can't find it.


Narrowed it to this function via gdb. it segfaults when the 2nd for loop starts / is supposed to start.

Code:
void file_reverse_output(FILE * file, FILE * newfile, const char type)
{
  // declare and initialize count + buffers + switch for tempfile
  int lines = file_num_lines(file);
  char buf[lines + 1][256];
  char str[256];

  // load buffer with lines
  for (int i = lines; i >= 0; i--) {
    strcpy(buf[i],fgets(str, 256, file));
  }
  // segfault here before next loop

  // output buffer in reverse order to file or screen
  // type is (p)rintf or (f)printf
  for (int i = 0; i <= lines; i++) {
    if (type == 'p') {
      if (i == 0) {
        printf("%s\n", buf[i]);
      } else {
        printf("%s", buf[i]);
      }
    } else if (type == 'f') {
      if (i == 0) {
        fprintf(newfile, "%s\n", buf[i]);
      } else {
        fprintf(newfile, "%s", buf[i]);
      }
    }
  }

  // reset file to beginning
  rewind(file);
}
 
Old 03-13-2023, 12:55 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,871
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
(Let's hope you call `rewind` after `file_num_lines`.)
You have an off-by-one error. Also you didn't check the return value of `fgets`.
Code:
void file_reverse_output(FILE * file, FILE * newfile, const char type)
{
  // declare and initialize count + buffers + switch for tempfile
  int lines = file_num_lines(file);
  char buf[lines + 1][256];
  char str[256];

  // load buffer with lines
  for (int i = lines-1; i >= 0; i--) {
    char *p= fgets(str, 256, file);
    if (!p) {
        fprintf(stderr, "Ouch\n");
        exit(12);
    }
    strcpy(buf[i],p);
  }
  // segfault here before next loop

  // output buffer in reverse order to file or screen
  // type is (p)rintf or (f)printf
  for (int i = 0; i < lines; i++) {
    if (type == 'p') {
      if (i == 0) {
        printf("%s\n", buf[i]);
      } else {
        printf("%s", buf[i]);
      }
    } else if (type == 'f') {
      if (i == 0) {
        fprintf(newfile, "%s\n", buf[i]);
      } else {
        fprintf(newfile, "%s", buf[i]);
      }
    }
  }

  // reset file to beginning
  rewind(file);
}
[/code]

Last edited by NevemTeve; 03-13-2023 at 01:09 AM.
 
Old 03-13-2023, 01:17 AM   #3
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,871
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
Guess you are working with a file that misses the terminating NewLine character. That should be solved otherwise, e.g.
Code:
static int file_num_lines(FILE *file) {
    int c;
    int lastc= '\n';
    size_t ln= 0;

    while ((c= fgetc(file))!=EOF) {
        if (c=='\n') ++ln;
        lastc= c;
    }
    rewind(file);
    if (lastc!='\n') ++ln;
    return ln;
}
or saving a line:
Code:
static int file_num_lines(FILE *file) {
    int c;
    int lastc= '\n';
    size_t ln= 0;

    while ((c= fgetc(file))!=EOF) {
        if (lastc=='\n') ++ln;
        lastc= c;
    }
    rewind(file);
    return ln;
}
Also with fgets:
Code:
void file_reverse_output(FILE * file, FILE * newfile, const char type)
{
  // declare and initialize count + buffers + switch for tempfile
  int lines = file_num_lines(file);
  char buf[lines + 1][256];
  char str[256];
  int l;

  // load buffer with lines
  for (int i = lines-1; i >= 0; i--) {
    char *p= fgets(str, 256, file);
    if (!p) {
        fprintf(stderr, "Ouch\n");
        exit(12);
    }
    l= strlen(p);
    if (l>0 && p[l-1]=='\n') p[--l]= '\0';
    strcpy(buf[i],p);
  }

  // output buffer in reverse order to file or screen
  // type is (p)rintf or (f)printf
  for (int i = 0; i < lines; i++) {
    if (type == 'p') {
        printf("%s\n", buf[i]);
    } else if (type == 'f') {
        fprintf(newfile, "%s\n", buf[i]);
    }
  }

  // reset file to beginning
  rewind(file);
}

Last edited by NevemTeve; 03-13-2023 at 01:28 AM.
 
1 members found this post helpful.
Old 03-13-2023, 03:48 PM   #4
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,910

Rep: Reputation: 5026Reputation: 5026Reputation: 5026Reputation: 5026Reputation: 5026Reputation: 5026Reputation: 5026Reputation: 5026Reputation: 5026Reputation: 5026Reputation: 5026
int lines = file_num_lines(file);
char buf[lines + 1][256];

If you're going to dynamically size buffers then use malloc(). VLAs were added in C99, but they were downgraded to an "optional feature" in C11.

Unless you have a good reason not to (such as a recursive function where stack usage might matter it's often just easier to allocate a large enough buffer to hold the largest entry rather than try and do anything clever.
 
Old 03-14-2023, 12:07 AM   #5
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,144

Original Poster
Rep: Reputation: 392Reputation: 392Reputation: 392Reputation: 392
Ok thank you. Will make some adjustments and report back. Thank you again.
 
Old 03-14-2023, 01:11 PM   #6
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,930

Rep: Reputation: 7321Reputation: 7321Reputation: 7321Reputation: 7321Reputation: 7321Reputation: 7321Reputation: 7321Reputation: 7321Reputation: 7321Reputation: 7321Reputation: 7321
the best tool to catch that kind of errors is valgrind. (ok, probably not the best, but definitely a very good tool).
 
Old 03-15-2023, 01:14 AM   #7
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,144

Original Poster
Rep: Reputation: 392Reputation: 392Reputation: 392Reputation: 392
Got it working. I followed the above suggestions. This now does both file or stdout depending on the flag used. I can see that I need to spend more time with validating functions.

Code:
void file_reverse_output(FILE * file, FILE * newfile, const char type)
{
  // declare and initialize count + buffers
  int lines = file_num_lines(file);
  char buf[lines + 1][256];
  char str[256];

  // load buffer with lines
  for (int i = lines - 1; i >= 0; i--) {
    char * ptr = fgets(str, 256, file);
    if (!ptr) {
      printf("buffer loading error!\n");
      printf("exiting. check line %d of your file.\n", i);
      exit(1);
    }
    strcpy(buf[i], ptr);
  }

  // output buffer in reverse order to file or screen
  // type is (p)rintf or (f)printf
  for (int i = 0; i <= lines - 1; i++) {
    if (type == 'p') {
      printf("%s", buf[i]);
    } else if (type == 'f') {
      fprintf(newfile, "%s", buf[i]);
    }
  }

  // reset file to beginning
  rewind(file);
}
 
Old 03-15-2023, 01:54 AM   #8
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,871
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
Also you can use `stdout` as `newfile` and drop parameter `type`.
 
1 members found this post helpful.
Old 03-23-2023, 04:16 AM   #9
Owel
LQ Newbie
 
Registered: Nov 2021
Location: Europe
Distribution: Slackware Linux mainly
Posts: 13

Rep: Reputation: Disabled
I suggest you learning Valgrind and GDB. With these two tools your debugging process will be easier.
 
1 members found this post helpful.
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
transmission-gtk/cli 2.82 segfault, can't find source of problem slacker_ Ubuntu 5 04-19-2015 06:12 AM
getting segfault when executing vmware-cmd Majed17 Linux - Software 0 05-30-2012 03:05 AM
C++: use gdb to find where segfault happens Ephracis Programming 10 03-09-2009 07:42 PM
I patched my RHEL 4 ES server and now I am getting segfault errors. sdaehn Linux - Newbie 5 08-25-2008 04:04 PM
Can't start ANY KDE program (segfault) damantis Linux - General 1 02-14-2005 05:10 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:33 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration