11 KiB
Common Compiler Troubleshooting Guide
Installation Issues
Problem: "gcc: command not found"
Solution: Install GCC
# Ubuntu/Debian
sudo apt-get install build-essential
# Fedora/RHEL
sudo dnf install gcc
# Arch
sudo pacman -S gcc
Problem: "nasm: command not found"
Solution: Install NASM assembler
# Ubuntu/Debian
sudo apt-get install nasm
# Fedora/RHEL
sudo dnf install nasm
# Arch
sudo pacman -S nasm
Problem: "fatal error: bits/libc-header-start.h: No such file"
Cause: Missing 32-bit development libraries
Solution: Install 32-bit support
# Ubuntu/Debian
sudo apt-get install gcc-multilib
# Fedora/RHEL
sudo dnf install glibc-devel.i686 libgcc.i686
Compilation Issues
Problem: Compiler fails to build
Error:
gcc -o common common.c
common.c:15:10: fatal error: stdio.h: No such file or directory
Solution: Install build essentials
sudo apt-get install build-essential
Problem: "Permission denied" when running compiler
Solution: Make compiler executable
chmod +x ./common
Or run directly:
gcc -o common common.c
./common source.cm output.asm
Assembly Issues
Problem: "error: invalid combination of opcode and operands"
Cause: NASM version incompatibility or corrupt assembly output
Debug Steps:
-
Check assembly output:
./common source.cm output.asm cat output.asm -
Verify NASM version:
nasm -version # Should be 2.x or higher -
Try manual assembly:
nasm -f elf32 output.asm -o output.o
Problem: "undefined reference to function_name"
Cause: Function called but not defined or linked
Solutions:
-
Missing function definition:
// Declare AND define the function int32 helper(int32 x) { return x * 2; } -
C library function not linked:
# Make sure you're linking with gcc gcc -m32 output.o -o program # NOT: ld output.o -o program -
External library needed:
gcc -m32 output.o -lm -o program # Link math library
Linker Issues
Problem: "cannot find -lgcc_s"
Cause: Missing 32-bit GCC support libraries
Solution:
sudo apt-get install gcc-multilib
Problem: "/usr/bin/ld: i386 architecture of input file is incompatible with i386:x86-64"
Cause: Mixing 32-bit and 64-bit object files
Solution: Ensure consistent 32-bit compilation:
nasm -f elf32 output.asm -o output.o # Must be elf32
gcc -m32 output.o -o program # Must use -m32
Problem: "undefined reference to main"
Cause: No main function in source
Solution: Add main function:
int32 main(void) {
// Your code here
return 0;
}
Runtime Issues
Problem: Segmentation fault
Common Causes:
-
Null pointer dereference:
int32 *ptr = 0; *ptr = 42; // CRASH: dereferencing NULLFix: Check pointers before dereferencing
if (ptr != 0) { *ptr = 42; } -
Array out of bounds:
int32 arr[10]; arr[10] = 5; // CRASH: index 10 is out of bounds (0-9)Fix: Check array bounds
if (index < 10) { arr[index] = 5; } -
Stack overflow (infinite recursion):
int32 recurse(int32 n) { return recurse(n); // CRASH: no base case }Fix: Add base case
int32 recurse(int32 n) { if (n <= 0) return 0; return recurse(n - 1); } -
Writing to read-only memory:
uint8 *str = "constant"; str[0] = 'C'; // CRASH: string literals are read-onlyFix: Use array for modifiable strings
uint8 str[20]; str[0] = 'C'; // OK
Problem: Wrong output values
Debug Steps:
-
Check integer overflow:
int8 x = 127; x = x + 1; // Wraps to -128 -
Check division by zero:
int32 result = 10 / 0; // Undefined behaviorFix:
if (divisor != 0) { result = dividend / divisor; } -
Check type truncation:
int32 large = 1000; uint8 small = (uint8)large; // Truncated to 232 (1000 % 256)
Problem: Program hangs / infinite loop
Common Causes:
-
Loop condition never false:
uint32 i = 10; while (i >= 0) { // INFINITE: unsigned i never < 0 i = i - 1; }Fix:
int32 i = 10; while (i >= 0) { i = i - 1; } -
Missing loop increment:
for (int32 i = 0; i < 10; ) { // Missing i++ // ... }
Compiler Error Messages
"line N: syntax error near 'token'"
Causes:
- Missing semicolon
- Mismatched braces/parentheses
- Invalid expression syntax
Debug:
- Check line N and surrounding lines
- Look for missing
;on previous line - Count braces:
{should match} - Check operator usage
Example:
int32 x = 10 // ERROR: missing semicolon
int32 y = 20;
"line N: Unknown char 'X'"
Cause: Invalid character in source
Common Examples:
- Smart quotes:
""instead of" - Non-ASCII characters
- Tab characters in wrong places
Fix: Use plain ASCII text editor
"line N: expected expression"
Cause: Invalid or incomplete expression
Example:
int32 x = ; // ERROR: no expression after =
int32 y = + 5; // ERROR: + needs left operand
"too many locals"
Cause: More than 256 local variables in a function
Solution:
- Reduce number of variables
- Use arrays instead of individual variables
- Split into multiple functions
"too many strings"
Cause: More than 512 string literals in program
Solution:
- Reuse string literals
- Build strings programmatically
- Use character arrays
Debugging Techniques
Print Debugging
void printf(uint8 *fmt, ...);
int32 main(void) {
int32 x = 10;
printf("x = %d\n", x); // Print values
int32 *ptr = &x;
printf("ptr = %p, *ptr = %d\n", ptr, *ptr); // Print pointers
return 0;
}
Check Assembly Output
./common source.cm output.asm
less output.asm # Review generated assembly
Look for:
- Correct function labels
- Proper stack setup
- Expected instructions
Use GDB
# Compile with debug info
gcc -m32 -g output.o -o program
# Run in debugger
gdb ./program
# GDB commands:
(gdb) break main # Set breakpoint at main
(gdb) run # Run program
(gdb) next # Step to next line
(gdb) print x # Print variable x
(gdb) backtrace # Show call stack
(gdb) quit # Exit gdb
Valgrind (Memory Errors)
# Install valgrind
sudo apt-get install valgrind
# Run with valgrind
valgrind --leak-check=full ./program
Common Mistakes
1. Assignment in Condition
Wrong:
if (x = 5) { // Assigns 5 to x, always true
// ...
}
Right:
if (x == 5) { // Compares x to 5
// ...
}
2. Infinite Loop with Unsigned
Wrong:
for (uint32 i = 10; i >= 0; i--) { // Infinite: unsigned never < 0
// ...
}
Right:
for (int32 i = 10; i >= 0; i--) {
// ...
}
3. Pointer vs. Value
Wrong:
void increment(int32 x) {
x = x + 1; // Only modifies local copy
}
int32 val = 5;
increment(val);
// val is still 5
Right:
void increment(int32 *x) {
*x = *x + 1; // Modifies through pointer
}
int32 val = 5;
increment(&val);
// val is now 6
4. Array Decay
Confusing:
int32 arr[10];
int32 *ptr = arr; // arr decays to pointer
// arr and &arr are different:
arr // Pointer to first element (type: int32*)
&arr // Pointer to entire array (type: int32(*)[10])
5. String Modification
Wrong:
uint8 *str = "Hello";
str[0] = 'h'; // CRASH: string literal is read-only
Right:
uint8 str[20] = "Hello"; // Array, modifiable
str[0] = 'h'; // OK
Performance Issues
Slow Compilation
Causes:
- Very large source file
- Many string literals
Solutions:
- None (no optimization flags)
- Split code into modules (not supported in single-file compiler)
Slow Execution
Common Causes:
-
Inefficient algorithms:
// O(n²) - slow for (int32 i = 0; i < n; i++) for (int32 j = 0; j < n; j++) // ... -
Excessive function calls:
// Fibonacci - exponential time int32 fib(int32 n) { if (n <= 1) return n; return fib(n-1) + fib(n-2); // Recomputes same values }Fix: Use iterative version or memoization
-
No optimizations: The compiler doesn't optimize. Write efficient code.
Getting Help
Information to Provide
When asking for help, include:
- Source code (minimal example that reproduces issue)
- Compilation command used
- Full error message (copy-paste, not screenshot)
- System information:
uname -a gcc --version nasm -version
Minimal Example
Reduce your code to the smallest program that shows the problem:
// Minimal example showing segfault
int32 main(void) {
int32 *ptr = 0;
*ptr = 42; // Crash here
return 0;
}
Check Examples First
Before reporting a bug, verify the example programs work:
make test
make examples
If examples work but your code doesn't, the issue is likely in your code, not the compiler.
Known Issues
64-bit Types
Issue: 64-bit arithmetic truncates to 32 bits
uint64 x = 5000000000; // Stored as 64-bit
uint64 y = x * 2; // Multiplied as 32-bit, overflow
Workaround: Use 32-bit types or implement 64-bit arithmetic manually
Single File Limitation
Issue: Cannot split code across multiple files
Workaround: Put all code in one file, use forward declarations
No Preprocessor
Issue: No #define, #include, etc.
Workaround:
- Use const variables instead of #define
- Copy/paste shared code
- Write wrapper script to concatenate files
Environment-Specific Issues
WSL (Windows Subsystem for Linux)
Usually works fine. If issues:
sudo apt update
sudo apt install gcc-multilib nasm
macOS
Problem: macOS doesn't support Linux ELF32
Solution: Use a Linux VM or Docker container
64-bit Only Systems
Problem: No 32-bit support installed
Solution: Install multilib packages (see Installation Issues above)
For more help, see the full manual (MANUAL.md) or examples (examples/)