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 10-18-2023, 01:45 AM   #1
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,149

Rep: Reputation: 393Reputation: 393Reputation: 393Reputation: 393
C - assert fails on 2nd run of same function.


Function in question.

Code:
void file_reverse_output(FILE * file,
                         FILE * newfile,
                         char * type)
{
  // we don't check newfile as NULL is a valid value
  assert(file);

  // declare & initialize
  long int len = file_num_lines(file);
  long int maxstr = 0;

  if (string_is_valid(type, "memsave")) {
    maxstr = file_longest_string(file);
    printf("memsave active\n");
  } else if (string_is_valid(type, "nomemsave")) {
    // this section fails assertion on file at getline_mem_alloc
    // below
    maxstr = MAX_BUFFER;
    printf("standard buffer active\n");
  } else {
    printf("specify memsave / nomemsave\n");
    exit(1);
  }

  char buffer[len][maxstr + 1];
  // initialize array. this solved an uninitialized value
  // error in valgrind down in the print loop. there may
  // be a better way to solve the error. this isn't the
  // fastest i'm guessing
  for (int i = 0; i <= len; i++) {
    for (int j = 0; j <= maxstr; j++) {
      buffer[i][j] = '\0';
    }
  }

  // loop through each line in text file, put in buffer for
  // future stdout / fprintf
  for (int i = 0; i < len; i++) {
    char * ptr = getline_mem_alloc(file);
    if (!ptr) {
      break;
    }
    // load lines into buffer and clear pointer
    strncpy(buffer[i],
            ptr,
            maxstr - 1);
    clear_char_ptr(ptr);
  }

  // reset file for next usage
  rewind(file);

  // print buffer in reverse order to either stdout or newfile
  for (int j = len - 1; j >= 0; j--) {
    no_more_newline(buffer[j]);
    if (newfile == NULL) {
      printf("%s\n",
             buffer[j]);
    } else {
      fprintf(newfile,
              "%s\n",
              buffer[j]);
    }
  }

  // rewind temp for next usage
  if (newfile) {
    rewind(newfile);
  }
}
I started screwing around with minimizing memory usage. Not fast but keeps the buffer only as big as it needs to be. My problem is when I run it from this test.c file.

Code:
#include <stdio.h>
#include <jmgeneral.h>
#include <string.h>

int main()
{
  FILE * file = fopen("testfile.txt", "r");
  if (!file) {
    printf("failed to open\n");
    return(1);
  }
  // this one works fine
  file_reverse_output(file, NULL, "memsave");
  // this run fails file assertion when it gets to 
  // getline function in file_reverse_output
  file_reverse_output(file, NULL, "nomemsave");
  fclose(file);
  file = NULL;
  return(0);
}
I can't figure why it works the first time then falls over the 2nd.

GIT - https://gitlab.com/jmgibson1981/mylibraries
 
Old 10-18-2023, 02:06 PM   #2
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,149

Original Poster
Rep: Reputation: 393Reputation: 393Reputation: 393Reputation: 393
I've isolated the issue. now I just can't see it.

Code:
if (string_is_valid(type, "memsave")) {
    // works when run longest string on file
    maxstr = file_longest_string(file);

  } else if (string_is_valid(type, "nomemsave")) {
    // doesn't work with static buffer number...
    maxstr = MAX_BUFFER;

  } else {
    printf("specify memsave / nomemsave\n");
    exit(1);
  }
when I call the function below it works. but won't work with a static buffer size, in this case my header is saying 1024.

Code:
long int file_longest_string(FILE * file, long int lines)
{
  assert(file);

  // declare & initialize
  long int len = 0;

  // loop through each line in file.
  // set return value to longest string in file
  for (int i = 0; i < lines; i++) {
    char * ptr = getline_mem_alloc(file);
    no_more_newline(ptr);
    long int j = strlen(ptr);
    if (j > len) {
      len = j;
    }
    clear_char_ptr(ptr);
  }

  // clean up & return
  rewind(file);
  return(len + 1);
}
 
Old 10-18-2023, 03:17 PM   #3
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,874
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
As a start: `file_longest_string` takes two arguments, not one.
 
Old 10-18-2023, 04:45 PM   #4
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,149

Original Poster
Rep: Reputation: 393Reputation: 393Reputation: 393Reputation: 393
Okay. For what it's worth I don't know how I missed that on copy, maybe I didn't copy the most recent like I thought I did. :/

Code:
  if (string_is_valid(type, "memsave")) {
    // works when function run on file for maxstr
    maxstr = file_longest_string(file, len);
  } else if (string_is_valid(type, "nomemsave")) {
    // doesn't work with static buffer number...
    maxstr = MAX_BUFFER;
  } else {
    printf("specify memsave / nomemsave\n");
    exit(1);
  }
 
Old 10-18-2023, 05:38 PM   #5
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,149

Original Poster
Rep: Reputation: 393Reputation: 393Reputation: 393Reputation: 393
Solved somewhat although I don't understand why it worked. I spent the last half hour or so inserting printf statements to return the pointer address. Moving them around until I isolated the section. For.... whatever reason? when I ran my array initialization loop it would null the file pointer. I'm at a loss as to the why... But it's fixed and clean pass through valgrind. Gonna test in a few other tools. Thank you for your assistance.

Git updated to reflect current working condition.

https://gitlab.com/jmgibson1981/mylibraries
 
Old 10-19-2023, 07:11 AM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,786

Rep: Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083Reputation: 2083
Code:
  char buffer[len][maxstr + 1];
  // initialize array. commented out because it changes the file
  // pointer to null. can't explain why. defintely a question
  // mark but this function in both modes passes valgrind cleanly
  // initialize array. commented out because it changes the file
  // pointer to null. can't explain why. defintely a question
  // mark but this function in both modes passes valgrind cleanly
  // now.
  /*for (int i = 0; i <= len; i++) {
    for (int j = 0; j <= maxstr; j++) {
You need either "buffer[len + 1][maxstr + 1]", or "for (int i = 0; i < len; i++) {..."

I think Valgrind can't (always?) notice overruns of stack variables, so that's why it misses this.
 
Old 10-19-2023, 09:01 AM   #7
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,874
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
Also I don't get what's the point in not-using memset or bzero (or rather calloc).
 
Old 10-19-2023, 11:11 AM   #8
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,883
Blog Entries: 13

Rep: Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931
It's difficult to help here because so much is missing and so much is not shown private functions.

Sorry but one needs to view the git repo or various other threads from the OP, it makes the effort difficult to assess for helping. Perhaps if you can provide a more clear summary in the original question.

Also you used 3 pointers, which are copies, modifying the contents may cause problems but you can't nullify a passing argument that is a stack copy of the original pointer. Therefore your problem was elsewhere.

Probably said it before but gdb would help immensely in your diagnostics and debugging.

I've seen this a lot, people start, do basic stuff, then they add a lot of their own experimentation, racing forwards with "can I do this", but overlooking better design and debug practices, instead running into problems where they could be solved fairly quickly or not exist if the fundamentals were concentrated on better.

Library functions exist for a reason by the way.
 
Old 10-19-2023, 11:15 AM   #9
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,149

Original Poster
Rep: Reputation: 393Reputation: 393Reputation: 393Reputation: 393
Yes I'm recently learning that to post for help I should combine all the needed parts into a single post. My apologies for that.
 
Old 10-19-2023, 07:38 PM   #10
jmgibson1981
Senior Member
 
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,149

Original Poster
Rep: Reputation: 393Reputation: 393Reputation: 393Reputation: 393
I'm still looking for a good way to find what I need in the standard libraries. So far I can just look at the headers and check the man pages on what I think might work. But then I get lazy and try to write it myself. Also still learning gdb. I'm trying to find that 3 pointer thing you mentioned but not seeing it. I don't doubt what you said but I'm clueless thus far. Still working on iut though.

*EDIT* I am also taking some time and learning GDB via CLI. Kept looking for a gui but gave up. Starting to see the value in using a text editor + cli stuff > ide. Base tools are more likely to not crash. Not that that is an issue with Debian in the first place for the most part of course...

Last edited by jmgibson1981; 10-19-2023 at 10:14 PM.
 
Old 10-20-2023, 04:40 AM   #11
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,883
Blog Entries: 13

Rep: Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931Reputation: 4931
Quote:
Originally Posted by jmgibson1981 View Post
I'm still looking for a good way to find what I need in the standard libraries. So far I can just look at the headers and check the man pages on what I think might work. But then I get lazy and try to write it myself. Also still learning gdb. I'm trying to find that 3 pointer thing you mentioned but not seeing it. I don't doubt what you said but I'm clueless thus far. Still working on iut though.
Each of the three arguments is a copy of a pointer, tyerefore altering any of them will not have impact outside of your function.
Code:
file_reverse_output(FILE * file,
                         FILE * newfile,
                         char * type)
Quote:
Originally Posted by jmgibson1981 View Post
*EDIT* I am also taking some time and learning GDB via CLI. Kept looking for a gui but gave up. Starting to see the value in using a text editor + cli stuff > ide. Base tools are more likely to not crash. Not that that is an issue with Debian in the first place for the most part of course...
From my signature, talks aboutusing emacs with gdb How To Debug Linux C Programs Effectively Using The Debugger
 
Old 10-20-2023, 05:41 AM   #12
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,976

Rep: Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337
Quote:
Originally Posted by ntubski View Post
I think Valgrind can't (always?) notice overruns of stack variables, so that's why it misses this.
https://valgrind.org/docs/manual/sg-manual.html
Code:
char a[10];

void main() {
    int i;
    char b;
    for (i=0; i<=10; i++) { b=a[i]; }
}
valgrind can do it, just need to add a command line flag:
Code:
/tmp$ valgrind --tool=exp-sgcheck  ./a.out
==3182== exp-sgcheck, a stack and global array overrun detector
==3182== NOTE: This is an Experimental-Class Valgrind Tool
==3182== Copyright (C) 2003-2015, and GNU GPL'd, by OpenWorks Ltd et al.
==3182== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==3182== Command: ./a.out
==3182== 
==3182== Invalid read of size 1
==3182==    at 0x4004FF: main (a.c:6)
==3182==  Address 0x60103b expected vs actual:
==3182==  Expected: global array "a" of size 10 in object with soname "NONE"
==3182==  Actual:   unknown
==3182==  Actual:   is 0 after Expected
==3182== 
==3182== 
==3182== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
 
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
prevent users to run the same script at the same time, on the same machine pvpnguyen Programming 2 09-05-2007 08:52 PM
bad: help me urgent just simple assert.h prob icylicious Programming 11 07-24-2006 02:53 PM
repeated message (tty1): ASSERT: "i <= nodes" in /usr/lib/qt-3.1.2/include/qvaluelist megahard Linux - General 4 01-17-2006 10:59 PM
make error: 'assert' undeclared (convex3D) mikshaw Linux - Software 2 03-25-2004 03:22 AM
kernel: ASSERT.... soba Linux - General 1 10-22-2003 06:51 PM

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

All times are GMT -5. The time now is 08:11 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