hm my program executes fine but then segfaults
Conversation
Notices
-
Embed this notice
new mir (mir@ice.ch3.st)'s status on Friday, 31-Jan-2025 17:08:53 JST new mir
-
Embed this notice
nyanide :nyancat_rainbow::nyancat_body::nyancat_face: (nyanide@lab.nyanide.com)'s status on Friday, 31-Jan-2025 17:08:50 JST nyanide :nyancat_rainbow::nyancat_body::nyancat_face:
@mir you do not need the length of the file nor do you need a buffer containing the entire file really, if you just want to print to stdout you could simplify down to these lines
#include <stdio.h> #include <unistd.h> void cat(char *filename) { FILE *fp = fopen(filename, "r"); char c; if (fp == NULL) { fprintf(stderr, "error: unable to open file\n"); _exit(-1); } while ((c = fgetc(fp)) != EOF) putchar(c); fclose(fp); } int main(int argc, char **argv) { if (argc <= 1) { fprintf(stderr, "error: no file specified\n"); _exit(-1); } for (int i = 1; i < argc; i++) cat(argv[i]); return 0; }
here's the implementation in action
-
Embed this notice
new mir (mir@ice.ch3.st)'s status on Friday, 31-Jan-2025 17:08:52 JST new mir
heres the program btw. test.txt and txt2.txt are files with keysmashes and copypasta in the working directory. im just running gcc mircat.c and it spits out a a.out that's executable
/* my first C program ever! gonna make a copy of `cat` with maybe extra features idk /* */ #include <stdio.h> #include <string.h> char* greeting = "bonjour"; char *fnames[] = {"test.txt","tst2.txt"}; int catfile (char* file){ FILE *stream ; int beg ; int end ; stream = fopen(file, "r") ; // type `FILE *` fseek(stream, 0, SEEK_SET); beg = ftell (stream); // should always be 0 fseek(stream, 0, SEEK_END); end = ftell (stream); //end of file char contents[end] ; for (int i = beg; i <= end ; i++) { fseek(stream, i, SEEK_SET); // go to next position contents[i] = fgetc (stream); // get char at said pos and assign it thusly }; printf ("file %s starts at %ld and ends at %ld\nits contents follow:\n%s\n\n", file, beg, end, contents ); }; int main (){ printf ("%s\n\n", greeting); for (int i = 0; i <= 2; i++) { catfile (fnames[i]); } ; return 0; } -
Embed this notice
nyanide :nyancat_rainbow::nyancat_body::nyancat_face: (nyanide@lab.nyanide.com)'s status on Friday, 31-Jan-2025 17:10:13 JST nyanide :nyancat_rainbow::nyancat_body::nyancat_face:
@mir @green garbage data from unused space on the buffer? -
Embed this notice
new mir (mir@ice.ch3.st)'s status on Friday, 31-Jan-2025 17:10:15 JST new mir
@green now, what's with these \377 and \375 (broken characters, they render even worse in a normal terminal)
-
Embed this notice
new mir (mir@ice.ch3.st)'s status on Friday, 31-Jan-2025 17:10:17 JST new mir
@green ope good catch
-
Embed this notice
imported green :rainforest_frog: (made in russia) (green@ice.ch3.st)'s status on Friday, 31-Jan-2025 17:10:21 JST imported green :rainforest_frog: (made in russia)
@mir int i = 0; i <= 2; i++ this actually iterates 3 times. it segfaults because it tries to read the 3rd element of the fnames array
-
Embed this notice
new mir (mir@ice.ch3.st)'s status on Friday, 31-Jan-2025 17:14:36 JST new mir
@nyanide@lab.nyanide.com i don't "just want to print to stdout". i want the option of doing other things with that buffer, even if the current code doesn't have anything for that.
-
Embed this notice
nyanide :nyancat_rainbow::nyancat_body::nyancat_face: (nyanide@lab.nyanide.com)'s status on Friday, 31-Jan-2025 17:27:48 JST nyanide :nyancat_rainbow::nyancat_body::nyancat_face:
@mir no biggie then, on unix we are blessed with stat(2), which you can use to retrieve file information including but not limited to the size of a file
#include <stdio.h> // perror is also here! #include <stdlib.h> // malloc, free #include <unistd.h> // _exit #include <sys/stat.h> #include <string.h> // memset char * cat(char *filename) { FILE *fp; char *buf; struct stat s; if (stat(filename, &s) != 0) { perror("stat"); _exit(-1); } fp = fopen(filename, "r"); if (fp == NULL) { fprintf(stderr, "error: unable to open file\n"); _exit(-1); } buf = malloc(s.st_size+1); memset(buf, s.st_size+1, 0); // fill the buffer with zeroes to ensure null termination // sizeof(char) is always 1 but i like being in the habit of writing these things for portability purposes fread(buf, sizeof(char), s.st_size, fp); fclose(fp); return buf; } int main(int argc, char **argv) { if (argc <= 1) { fprintf(stderr, "error: no file specified\n"); _exit(-1); } for (int i = 1; i < argc; i++) { char *buf = cat(argv[i]); printf("%s", buf); free(buf); buf = NULL; } return 0; } -
Embed this notice
nyanide :nyancat_rainbow::nyancat_body::nyancat_face: (nyanide@lab.nyanide.com)'s status on Friday, 31-Jan-2025 17:32:05 JST nyanide :nyancat_rainbow::nyancat_body::nyancat_face:
@mir minor bugfix cause i forgot to check the return value of malloc lmao -
Embed this notice
nyanide :nyancat_rainbow::nyancat_body::nyancat_face: (nyanide@lab.nyanide.com)'s status on Friday, 31-Jan-2025 17:51:43 JST nyanide :nyancat_rainbow::nyancat_body::nyancat_face:
@green @mir >some prefer to put pointer next to type and other next to the name
in c you don't really explicitly define a char*, variables are assumed char (or other type) unless you point a star next to them,
you can't do char* b, a, because only b is recognized as a ptr
thus it's better to put the type next to the name but like, yeah I guess personal preference -
Embed this notice
imported green :rainforest_frog: (made in russia) (green@ice.ch3.st)'s status on Friday, 31-Jan-2025 17:51:45 JST imported green :rainforest_frog: (made in russia)
@mir here you go. i hope my voice is cute :neocat_floof_aww:
-
Embed this notice
imported green :rainforest_frog: (made in russia) (green@ice.ch3.st)'s status on Friday, 31-Jan-2025 18:00:43 JST imported green :rainforest_frog: (made in russia)
@mir@ice.ch3.st @nyanide@lab.nyanide.com the portable way to check how big a file is, would be with fseek/ftell, just like in mir's first code. also why are you using _exit instead of exit
-
Embed this notice
nyanide :nyancat_rainbow::nyancat_body::nyancat_face: (nyanide@lab.nyanide.com)'s status on Friday, 31-Jan-2025 18:01:28 JST nyanide :nyancat_rainbow::nyancat_body::nyancat_face:
@green @mir i did man 2 exit and that's what i found so i just kinda rolled with it, normally i do exit lmao
also yeah I mentioned in a post edit it's not portable. I don't know if that federated. -
Embed this notice
imported green :rainforest_frog: (made in russia) (green@ice.ch3.st)'s status on Friday, 31-Jan-2025 18:08:36 JST imported green :rainforest_frog: (made in russia)
@mir@ice.ch3.st @nyanide@lab.nyanide.com yeah, because _exit is the syscall. that's why it would be in the syscall(2) manual. the exit function in c also does other stuff, like flushing the buffers of all open files. the man section to look for c fucntions is usually 3
-
Embed this notice