2010-02-12 13 views
11

Questo codice viene compilato, ma senza sorprese, non riesce durante il collegamento (non principale trovato):In C, main non deve essere una funzione?

Listing 1:

void main(); 

errore link: \ MinGW \ lib \ libmingw32.a (principale. o):. main.c :(testo + 0x106) undefined reference to _WinMain @ 16'

Ma, il codice qui sotto compila e collega bene, con un avvertimento:

Listing 2:

void (*main)(); 

avvertimento: 'principale' è di solito una funzione di

Domande:

  1. In vendita 1, linker dovrebbe avere lamentavano per la mancanza "principale". Perché sta cercando _WinMain @ 16?

  2. L'eseguibile generato dall'elenco 2 semplicemente si arresta in modo anomalo. Che cos'è il motivo ?

Grazie per il vostro tempo.

+1

Si blocca perché il dereferenziamento 'void (* main)();' esegue un puntatore NULL (se questo è il codice completo) – Mawg

risposta

4

Caso 1. è specifico per Windows - il compilatore genera probabilmente il simbolo _WinMain quando main è definito correttamente.

Caso 2. - avete un puntatore, ma variabile come static è inizializzato a zero, quindi l'incidente.

+1

Il compilatore di solito richiede "_WinMain" quando sviluppa applicazioni per Windows. Molti compilatori hanno un modello * console *, che richiede 'main', ma non fornisce tutte le chicche per le finestre, solo per la moda C. –

+0

Thomas, grazie, tanto lo so. Semplicemente non ero sicuro che VS forse "impianta" _WinMain automaticamente nei programmi della console. –

1

Prova ridefinendo come int main(int argc, char *argv[])

Quello che hai è un errore di linker. Il linker si aspetta di trovare una funzione con che "firma" - non vuoto con nessun parametro

Vedi http://publications.gbdirect.co.uk/c_book/chapter10/arguments_to_main.html ecc

+3

La funzione main non ha bisogno di avere argomenti. int main (void) è anche una firma perfettamente valida. Tuttavia, in C (a differenza di C++) int main() significa che può accettare qualsiasi argomento, che è uno stile cattivo, ma AFAIK è ancora legale. – Tronic

+0

Concordato (spiacente) Vedi http://en.wikipedia.org/wiki/Main_function_%28programming%29#C_and_C.2B.2B Ma, in ogni caso, ha ovviamente un errore del linker perché non viene dichiarata alcuna funzione principale (concordato?). Alcuni ambienti (in particolare quelli per lo sviluppo di programmi basati su GUI) forniranno questo automaticamente. – Mawg

28

vero, main non ha bisogno di essere una funzione. Questo è stato sfruttato in alcuni programmi offuscati che contengono codice di programma binario in un array chiamato main.

Il tipo di ritorno di main() deve essere int (non void). Se il linker sta cercando WinMain, pensa che tu abbia un'applicazione GUI.

+14

http://www.ioccc.org/years.html#1984_mullender –

+0

+1, non lo sapevo :) –

6

Nella maggior parte dei sistemi di compilazione C, non vi sono informazioni sul tipo associate ai simboli collegati. Potresti dichiarare come ad esempio

char main[10]; 

e il linker sarebbe perfettamente felice. Come hai notato, il programma probabilmente si arresterebbe in modo anomalo, a meno che tu abbia inizializzato abilmente il contenuto dell'array.

Il tuo primo esempio non definisce main, lo dichiara solo, quindi l'errore del linker.

Il secondo esempio definisce main, ma in modo errato.

+0

> Il secondo esempio definisce main, ma non correttamente. Questo significa che il compilatore alloca un po 'di spazio per questo codice? 'void (* main)();' Non si tratta solo di una dichiarazione, i punti principali di una funzione che richiede un numero non specificato di argomenti e non restituisce nulla? (al contrario di una definizione)? – Gowtham

+1

+1 per il post. Puoi dare un esempio di main dichiarato come array e il codice funzionerà? Sono abbastanza curioso di saperlo. Non ho mai incontrato un simile codice. – Jay

+1

In passato era più facile fare cose del genere. Per un esempio di un array eseguibile vedere http://stackoverflow.com/questions/2251859/cant-find-my-syntax-error-vc-says-theres-one/2251892#2251892 –

2

Hai dichiarato un puntatore a funzione denominato main e il linker ti ha avvertito che ciò non avrebbe funzionato.

Il messaggio _WinMain ha a che fare con il funzionamento dei programmi Windows. Sotto il livello del runtime C, un eseguibile di Windows ha un WinMain.

0

Nell'elenco 1, stai dicendo "C'è un main() definito altrove nel mio codice --- lo prometto!". Ecco perché compila. Ma tu stai mentendo lì, motivo per cui il link fallisce. Il motivo per cui si verifica l'errore WinMain16 mancante è perché le librerie standard (per il compilatore Microsoft) contengono una definizione per main(), che chiama WinMain(). In un programma Win32, dovresti definire WinMain() e il linker userebbe la versione di libreria di main() per chiamare WinMain().

Nel Listato 2, si ha un simbolo definito principale definito, quindi sia il compilatore & il linker sono felici, ma il codice di avvio proverà a chiamare la funzione che è in posizione "main", e scoprirà che non c'è davvero un funzione lì, e crash.

+0

Questo significa che il compilatore alloca un po 'di spazio per questo codice? 'void (* main)();' Questa non è solo una dichiarazione, i punti principali di una funzione che prende un numero non specificato di argomenti e non restituisce nulla? (al contrario di una definizione)? – Gowtham

+0

No. Alloca lo spazio per un * puntatore * a una funzione che accetta un numero non specificato di argomenti e non restituisce nulla. 'char * main;' o anche 'void * main;' avrebbe realizzato la stessa cosa. –

0

1.) Una funzione (compilatore/piattaforma) dipendente viene chiamata prima che venga eseguito il codice in main e quindi il comportamento (_init in caso di linux/glibc).
2) Il blocco del codice nel secondo caso è giustificato dal fatto che il sistema non è in grado di accedere ai contenuti del simbolo main come una funzione che in realtà è un puntatore a funzione che punta alla posizione arbitraria.

3

Su piattaforme Windows l'unità principale del programma è WinMain se non si imposta il programma come app per console. Il "@ 16" significa che è in attesa di 16 byte di parametri. Quindi il linker sarebbe abbastanza felice con te finché gli darai una funzione chiamata WinMain con 16 byte di parametri.

Se si desiderato un'app console, questa è la tua indicazione che hai incasinato qualcosa.

Problemi correlati