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 |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
03-13-2023, 12:22 AM
|
#1
|
Senior Member
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,185
|
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);
}
|
|
|
03-13-2023, 12:55 AM
|
#2
|
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,924
|
(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.
|
|
|
03-13-2023, 01:17 AM
|
#3
|
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,924
|
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.
|
03-13-2023, 03:48 PM
|
#4
|
LQ Veteran
Registered: May 2008
Posts: 7,004
|
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.
|
|
|
03-14-2023, 12:07 AM
|
#5
|
Senior Member
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,185
Original Poster
|
Ok thank you. Will make some adjustments and report back. Thank you again.
|
|
|
03-14-2023, 01:11 PM
|
#6
|
LQ Addict
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 22,702
|
the best tool to catch that kind of errors is valgrind. (ok, probably not the best, but definitely a very good tool).
|
|
|
03-15-2023, 01:14 AM
|
#7
|
Senior Member
Registered: Jun 2015
Location: Tucson, AZ USA
Distribution: Debian
Posts: 1,185
Original Poster
|
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);
}
|
|
|
03-15-2023, 01:54 AM
|
#8
|
Senior Member
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,924
|
Also you can use `stdout` as `newfile` and drop parameter `type`.
|
|
1 members found this post helpful.
|
03-23-2023, 04:16 AM
|
#9
|
LQ Newbie
Registered: Nov 2021
Location: Europe
Distribution: Slackware Linux mainly
Posts: 13
Rep:
|
I suggest you learning Valgrind and GDB. With these two tools your debugging process will be easier.
|
|
1 members found this post helpful.
|
All times are GMT -5. The time now is 04:13 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|