Files
common/TROUBLESHOOTING.md
2026-03-14 14:14:37 -04:00

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:

  1. Check assembly output:

    ./common source.cm output.asm
    cat output.asm
    
  2. Verify NASM version:

    nasm -version  # Should be 2.x or higher
    
  3. 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:

  1. Missing function definition:

    // Declare AND define the function
    int32 helper(int32 x) {
        return x * 2;
    }
    
  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
    
  3. 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:

  1. Null pointer dereference:

    int32 *ptr = 0;
    *ptr = 42;  // CRASH: dereferencing NULL
    

    Fix: Check pointers before dereferencing

    if (ptr != 0) {
        *ptr = 42;
    }
    
  2. 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;
    }
    
  3. 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);
    }
    
  4. Writing to read-only memory:

    uint8 *str = "constant";
    str[0] = 'C';  // CRASH: string literals are read-only
    

    Fix: Use array for modifiable strings

    uint8 str[20];
    str[0] = 'C';  // OK
    

Problem: Wrong output values

Debug Steps:

  1. Check integer overflow:

    int8 x = 127;
    x = x + 1;  // Wraps to -128
    
  2. Check division by zero:

    int32 result = 10 / 0;  // Undefined behavior
    

    Fix:

    if (divisor != 0) {
        result = dividend / divisor;
    }
    
  3. Check type truncation:

    int32 large = 1000;
    uint8 small = (uint8)large;  // Truncated to 232 (1000 % 256)
    

Problem: Program hangs / infinite loop

Common Causes:

  1. 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;
    }
    
  2. 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:

  1. Check line N and surrounding lines
  2. Look for missing ; on previous line
  3. Count braces: { should match }
  4. 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:

  1. Reduce number of variables
  2. Use arrays instead of individual variables
  3. Split into multiple functions

"too many strings"

Cause: More than 512 string literals in program

Solution:

  1. Reuse string literals
  2. Build strings programmatically
  3. 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:

  1. Inefficient algorithms:

    // O(n²) - slow
    for (int32 i = 0; i < n; i++)
        for (int32 j = 0; j < n; j++)
            // ...
    
  2. 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

  3. No optimizations: The compiler doesn't optimize. Write efficient code.


Getting Help

Information to Provide

When asking for help, include:

  1. Source code (minimal example that reproduces issue)
  2. Compilation command used
  3. Full error message (copy-paste, not screenshot)
  4. 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/)