For my Programming 102 class we are asked to deliver C code that compiles and runs under Linux. I don\'t have enough spare space on my hard drive to install Linux alongside Wind
A segmentation fault means that you tried to access memory you couldn't, which usually means you tried dereferencing a null pointer or you double-deleted memory or got a wild pointer. There's two reasons why you might have appeared to be fine on cygwin and not on Linux: either it was an issue with the memory managers, or you got more lucky on one of them than the other. It is almost certainly an error with your code.
To fix this, look at your pointer use. Consider substituting smart pointers for raw pointers. Consider doing a search for delete and zeroing the pointer immediately afterwards (it's safe to try to delete a null pointer). If you can get a crack at Linux, try getting a stack trace through gdb and see if there's anything obviously wrong at the line it happens. Examine how you use all pointers that aren't initialized. If you have access to a memory debugging tool, use it.
Cygwin's version of gcc may have other default flags and tweaked settings (wchar_t being 2 bytes for example), but i doubt it is specifically more "lax" with code and even so - your code should not crash. If it does, then most probably there is a bug in your code that needs be fixed. For example your code may depend on a particular size of wchar_t or may execute code that's not guaranteed to work at all, like writing into string literals.
If you write clean code then it runs also on linux. I'm currently running firefox and the KDE desktop which together consist of millions of C++ lines, and i don't see those apps crashing :)
I recommend you to paste your code into your question, so we can look what is going wrong.
In the meantime, you can run your program in gdb
, which is a debugger for linux. You can also compile with all mudflap checks enabled and with all warnings enabled. mudflaps checks your code at runtime for various violations:
[js@HOST2 cpp]$ cat mudf.cpp
int main(void)
{
int a[10];
a[10] = 3; // oops, off by one.
return 0;
}
[js@HOST2 cpp]$ g++ -fmudflap -fstack-protector-all -lmudflap -Wall mudf.cpp
[js@HOST2 cpp]$ MUDFLAP_OPTIONS=-help ./a.out
... showing many options ...
[js@HOST2 cpp]$ ./a.out
*******
mudflap violation 1 (check/write): time=1234225118.232529 ptr=0xbf98af84 size=44
pc=0xb7f6026d location=`mudf.cpp:4:12 (main)'
/usr/lib/libmudflap.so.0(__mf_check+0x3d) [0xb7f6026d]
./a.out(main+0xb9) [0x804892d]
/usr/lib/libmudflap.so.0(__wrap_main+0x4f) [0xb7f5fa5f]
Nearby object 1: checked region begins 0B into and ends 4B after
mudflap object 0x9731f20: name=`mudf.cpp:3:11 (main) int a [10]'
bounds=[0xbf98af84,0xbf98afab] size=40 area=stack check=0r/3w liveness=3
alloc time=1234225118.232519 pc=0xb7f5f9fd
number of nearby objects: 1
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
....
There are many mudflap checks you can do, and the above runs a.out using the default options. Another tools which helps for those kind of bugs is valgrind
, which can also help you find leaks or off by one bugs like above. Setting the environment variable "MALLOC_CHECK_" to 1 will print messages for violations too. See the manpage of malloc
for other possible values for that variable.
For checking where your program crashes you can use gdb
:
[js@HOST2 cpp]$ cat test.cpp
int main() {
int *p = 0;
*p = 0;
}
[js@HOST2 cpp]$ g++ -g3 -Wall test.cpp
[js@HOST2 cpp]$ gdb ./a.out
...
(gdb) r
Starting program: /home/js/cpp/a.out
Program received signal SIGSEGV, Segmentation fault.
0x080483df in main () at test.cpp:3
3 *p = 0;
(gdb) bt
#0 0x080483df in main () at test.cpp:3
(gdb)
Compile your code with -g3 to include many debugging information, so gdb can help you find the precise lines where your program is crashing. All the above techniques are equally applicable for C and C++.
Like others have said, you might want to post some of your code here, even if that's not the real point of your question. It might still be a good learning experience to have everyone here poke through your code and see if they can find what caused the segfault.
But yeah, the problem is that there are so many platform-dependent, as well as basically random, factors influencing a C program. Virtual memory means that sometimes, accessing unallocated memory will seem to work, because you hit an unused part of a page that's been allocated at some earlier point. Other times, it'll segfault because you hit a page that hasn't been allocated to your process at all. And that is really impossible to predict. It depends on where your memory was allocated, was it at the edge of a page, or in the middle? That's up to the OS and the memory manager, and which pages have been allocated so far, and...... You get the idea. Different compilers, different versions of the same compilers, different OS'es, different software, drivers or hardware installed on the system, anything can change whether or not you get a segfault when you access unallocated memory.
As for the TA's claim that cygwin is more "lax", that's rubbish, for one simple reason. Neither compiler caught the bug! If the "native" GCC compiler had truly been less lax, it would have given you an error at compile-time. Segfaults are not generated by the compiler. There's not much the compiler can do to ensure you get a segfault instead of a program that seemingly works.
Some hints:
Post your code. I'll bet you will get some good input that will make you a better programmer.
Turn on warnings with the -wall
option and correct any problems that are reported. Again, it can help make you a better programmer.
Step through the code with a debugger. Besides helping you understand where the problem is, it will help make you a better programmer.
Continue to use Subversion or other source code control system.
Never blame the compiler (or OS or hardware) until you are sure you've pinpointed the problem. Even then, be suspicious of your own code.
GCC on Linux is source-code identical to GCC on Cygwin. Differences between the platforms exist occur because of the Cygwin POSIX emulation layer and the underlying Windows API. It's possible the extra layers are more forgiving than the underlying hardware, but that's not be counted on.
Since it's homework, I'd say posting code is an even better idea. What better way to learn than getting input from professional programmers? I'd recommend crediting any suggestions you implement in nearby comments, however.
A segmentation fault is the result of accessing memory at a non-existent (or previously freed) address. What I find very interesting is that the code did NOT segfault under cygwin. That could mean that your program used a wild pointer to some other processes' address space and was actually able to read it (gasp), or (more likely) the code that actually caused the segfault was not reached until the program was run under Linux.
I recommend the following:
Once your working under Linux (i.e. shelled into your VPS), try working with the following programs:
Also, you can try libraries like electric fence to catch these kinds of things as they happen while your program is running.
Finally, make sure -Wall is passed to gcc, you want the warnings it would convey.
I haven't heard of anything specific about GCC weirdness under Cygwin but in your case it would probably be a good idea to use the -Wall command-line option to gcc to show all warnings, to see if it finds anything that might be causing the segfault in your code.