Happy_Dude #1 Posted April 25, 2004 I'm attempting to compile distella on my debain box and it's looking promising. Except for this last error I can't understand. distella.c:89: warning: return type of `main' is not `int' Line 89 is just a "{" So I'm guessing the error is in this line (88 ) void main(int argc,char *argv[]) If I remove void it compiles but I get a segmentation fault any ideas? Quote Share this post Link to post Share on other sites
+kisrael #2 Posted April 25, 2004 I'm attempting to compile distella on my debain box and it's looking promising.Except for this last error I can't understand. distella.c:89: warning: return type of `main' is not `int' Line 89 is just a "{" So I'm guessing the error is in this line (88 ) void main(int argc,char *argv[]) If I remove void it compiles but I get a segmentation fault any ideas? I don't know enough to really help you, just to point out the historical nature of the problem....main is...well, the main routine the program, the one the program stsarts up with. Technically it should always be set to return an int, since back in the day that's how other programs could tell if your program suceeded (returned 0) or failed (returned some other error code). Removing the void means it goes to the default of returning an int, and so it stops complaining. If you did a "return 0;" at the end, that might be better. But unfortunately I don't think any of this really explains why you're getting the segfault, it's probably all a red herring. :-( Quote Share this post Link to post Share on other sites
+kisrael #3 Posted April 25, 2004 I mean to say, a return 0; right before the } that ends the main() function Quote Share this post Link to post Share on other sites
Ze_ro #4 Posted April 25, 2004 Except for this last error I can't understand. distella.c:89: warning: return type of `main' is not `int' Traditionally in Unix (and therefor Linux), programs should return an integer... the idea being that this return value is available to whatever program started it in the first place (likely your shell), so it can tell whether the program was successful or not, or any other pertinent information. A "smart" compiler sees that this program doesn't adhere to this Unixism, and flags it as a warning. You should be able to just ignore the warning and go on with life... but I'm guessing that the Makefile is using a "-Werror" flag, which tells the compiler to consider all warnings as fatal errors. If you get rid of the -Werror flag, it will likely compile fine. Line 89 is just a "{" So I'm guessing the error is in this line (88 ) void main(int argc,char *argv[]) If I remove void it compiles but I get a segmentation fault any ideas? The correct change would be to change "void" into "int". Keep in mind that since the program was written with "void main()", then it likely never attempts to return anything. If you change it to "int void()", you might get a completely different warning about the fact that the program said it would return a value, yet never does. I'm not sure if this is the source of the segmentation fault though... that seems like it might be a seperate issue altogether. --Zero Quote Share this post Link to post Share on other sites
EricBall #5 Posted April 26, 2004 I'm attempting to compile distella on my debain box and it's looking promising.Except for this last error I can't understand. distella.c:89: warning: return type of `main' is not `int' If I remove void it compiles but I get a segmentation fault any ideas? int main(int argc,char *argv[]) should get rid of the warning, however, issues with what main returns shouldn't cause a seg fault. You may need to look at the coredump using your debugger (dbx?) to see where it is dying. Quote Share this post Link to post Share on other sites
Happy_Dude #6 Posted April 26, 2004 int main(int argc,char *argv[]) should get rid of the warning, however, issues with what main returns shouldn't cause a seg fault. You may need to look at the coredump using your debugger (dbx?) to see where it is dying. Yep, Changing void to int works. I still get a seg fault, but only when I run it without any arguments. Other than that it works just like it's supposed to Thanks for the help. Quote Share this post Link to post Share on other sites
+kisrael #7 Posted April 26, 2004 I'm attempting to compile distella on my debain box and it's looking promising.Except for this last error I can't understand. distella.c:89: warning: return type of `main' is not `int' If I remove void it compiles but I get a segmentation fault any ideas? int main(int argc,char *argv[]) should get rid of the warning, however, issues with what main returns shouldn't cause a seg fault. You may need to look at the coredump using your debugger (dbx?) to see where it is dying. In Java, if a function returns something, it has to return it. What's the default if you don't specify a return, and just let the function end.... return 0? Glancing briefly at the source, I wonder if argc/argv are handled different with this compiler than on a typical DOS system, so that if there aren't any arguments, it still tries to look in the argv array. or something. If someone knew just a dash of C and had a compiler it would be easy enough to do some printf debugging. Quote Share this post Link to post Share on other sites
Tom #8 Posted April 26, 2004 [in Java, if a function returns something, it has to return it. What's the default if you don't specify a return, and just let the function end.... return 0? nah, return values are passed through registers in c, on compilers for 80x86 architecture usually in al/ax/eax. now if you don't have a return statement in a function that should have one and your function terminates, the caller will get as return value whatever garbage was in eax when the function terminated. this is certainly not the reason why distella coredumps, because in the case of the main() function the return value isn't really important (eh...sort of=). when main() terminates, it will return to the startup/cleanup code of the c runtime library which called main() (main is actually not the real program entry point for the operating system, it's just the entry point from a c programmer's point of view). the runtime library in turn doesn't care about that return value neither, it simply passes it to the operating system which doesn't care about it neither. (the user or parent process that spawned the program might care about it, though). anyway, in any case, not returning a value in a function that is declared to return one is of course an error and one should set the error level of a compiler strict enough so that it treats this as an error, rather than only printing a warning. this reminds me, i should find out to do that for cc65 aswell... Quote Share this post Link to post Share on other sites
Tom #9 Posted April 26, 2004 i found the bug (sort of, haven't fixed it yet). the problem is in the code that parses the command line (starts around line 127) it doesn't have anything do do with command line stuff differences between linux and dos, it's rather that dos can't detect memory violations (how should it, being a bloody real mode operating system). and by a perverse chance the bug doesn't make the dos version crash while (--argc > 1 && (*++argv)[0] == '-') while (c = *++argv[0]) switch(c) { case 'a': aflag = 0; break; case 'c': cflag = 1; i=0; while (*++argv[0] != '') config[i++] = *argv[0]; config[i]=*argv[0]--; fprintf(stderr,"Using %s config filen",config); break; case 'd': dflag = 0; break; case 'o': oflag = *++argv[0]; switch (oflag) { case '1': strcpy(orgmnc," ORG "); break; case '2': strcpy(orgmnc," *="); break; case '3': strcpy(orgmnc," .OR "); break; default: fprintf(stderr,"Illegal org type %cn",oflag); break; } break; case 'p': pflag = 1; break; case 's': sflag = 1; break; case 'i': intflag = 1; break; case 'r': rflag = 1; break; case 'f': fflag = 1; break; case '7': a78flag = 1; break; case 'b': bflag = 1; break; case 'k': kflag = 1; break; default: fprintf(stderr,"DiStella: illegal option %cn",c); exit(1); } strcpy(file,*++argv); if (argc != 1) { fprintf(stderr,"DiStella v3.00 - February 8, 2003n"); fprintf(stderr,"nUse: DiStella [options] filen"); fprintf(stderr," options:n"); fprintf(stderr," -7 Use Atari 7800 MARIA equates and file sizesn"); fprintf(stderr," -a Turns 'A' off in accumulator instructionsn"); fprintf(stderr," -c Defines optional config file to use. (e.g. -cpacman.cfg)n"); fprintf(stderr," (see distella.txt for additional information)n"); fprintf(stderr," -d Disables automatic code determinationn"); fprintf(stderr," -f Forces correct address lengthn"); fprintf(stderr," -i Process DMA interrupt Vector (7800 mode)n"); fprintf(stderr," If 2600 mode, enables -b optionn"); fprintf(stderr," -b Process BRK interrupt Vector (2600 and 7800 mode)n"); fprintf(stderr," -k Enable POKEY equates (7800 mode only, auto-detected if a78 file)n"); fprintf(stderr," -o# ORG variation: # = 1- ORG $XXXX 2- *=$XXXX 3- .OR $XXXXn"); fprintf(stderr," -p Insert psuedo-mnemonic 'processor 6502'n"); fprintf(stderr," -r Relocate calls out of address rangen"); fprintf(stderr," -s Cycle countn"); fprintf(stderr,"n Example: DiStella -pafs pacman.bin > pacman.sn"); fprintf(stderr," Example: DiStella -paf7ikscball.cfg ballblaz.bin > ballblaz.asmn"); fprintf(stderr,"n Email: [email protected] or [email protected]"); fprintf(stderr," Version 3.0 updates, email [email protected]"); exit(0); } while (--argc > 1 && (*++argv)[0] == '-') argc is decremented first (prefix --). if the command line was empty (in this case argc was 1) argc is now zero, and the loop terminates. argv isn't touched, because of short circuit evaluation: as soon as the first expression is false, the && expression can never be true, and the argv stuff isn't executed. fine. so the loop exits, and continues with the strcpy() after the loop: strcpy(file,*++argv); here, argv is first incremented (prefix --), then dereferenced and the resulting value is passed to strcpy() which tries to read from that location. i debugged it under win32, where *argv (after argv is incremented) is 0, so strcpy tries to read from 0x00000000 => boom, segmentation fault. dos has no way to detect that, and strcpy will happily copy garbage to file, until it encounters a terminating zero. file is a character array on the stack, so strcpy might be screwing up main's stack frame, but apparently this doesn't lead to a crash because after that (and a few fprintf calls) exit() is called. it's also possible that strcpy stumbles over a terminating zero before it stomps over the end of file. who knows =) i'd say the bug can be fixed by moving the strcpy call after the if statement that terminates the program. edit: it would fix that particular bug, but you're still relying on the user not to enter a filename longer than 49 characters (file is defined as "char file[50]"). blah. neat how you can shoot yourself in the foot with c, isn't it ? (and yes, the distella code is butt ugly:) Quote Share this post Link to post Share on other sites
+kisrael #10 Posted April 26, 2004 Interesting! (Are you part of the Distella group or just an interested party?) Frankly, crap like this is exactly why I never do increment/decrement "inline"... I always adjust the value with ++ or -- and THEN work with it, the whole prefix/postfix thing has always seemed awfully sketchy to me, using that is some small possible performance gain at the price of a small amount of clarity...(plus lil' oopsies like this!) and I always go for clarity over performance. Quote Share this post Link to post Share on other sites
Tom #11 Posted April 26, 2004 kirk: no, i just looked at this because a) happy_dude brought it up and i was bored b) i'd like to have a native win32 build of distella, because i hate it when you're working on the windows console (having long pathnames displayed in the prompt) and then you start a dos application and after that the path names are screwed up with that stupid ~ notation about ++/-- operators: while they can greatly obfuscate code, mixing them with all kinds of other statements often won't give you any performance gain. a good compiler will generate exactly the same machine code from the following three bits of code: strcpy(file,*++argv); argv++; strcpy(file, *argv); ++argv; strcpy(file, *argv); Quote Share this post Link to post Share on other sites
+kisrael #12 Posted April 27, 2004 kirk:no, i just looked at this because a) happy_dude brought it up and i was bored b) i'd like to have a native win32 build of distella, because i hate it when you're working on the windows console (having long pathnames displayed in the prompt) and then you start a dos application and after that the path names are screwed up with that stupid ~ notation Heh, I tend to have vague paranoia about Windows' handling of long filenames and/or using space as a file delimator, so all my important stuff still tends to conform to old 8.3 (my atari coding was in c:datadevatariwork , for instance ) about ++/-- operators: while they can greatly obfuscate code, mixing them with all kinds of other statements often won't give you any performance gain. Well, the languages I use ++ in are Java, Perl, and sometimes Javascript, so usually I'm not in a position to sweat cycles like that anyway :-) (It's a far cry from the 6507 ASM!) Thanks for your explanations. My C is probably way too rusty at this point, but again the languages I use all deeply reflect its syntax. Quote Share this post Link to post Share on other sites