DedSec Project

undefined reference — DedSec Project

C linker undefined reference — εντοπισμός υλοποίησης που λείπει Γιατί η μεταγλώττιση περνά αλλά η σύνδεση αποτυγχάνει Η δήλωση συνάρτησης ενημερώνει τον μεταγλωττιστή C για τον τρόπο κλήσης…

C linker undefined reference — εντοπισμός υλοποίησης που λείπει

Γιατί η μεταγλώττιση περνά αλλά η σύνδεση αποτυγχάνει

Η δήλωση συνάρτησης ενημερώνει τον μεταγλωττιστή C για τον τρόπο κλήσης της, αλλά δεν δημιουργεί τον κώδικα της συνάρτησης. Κάθε αρχείο .c μετατρέπεται συνήθως σε ξεχωριστή μονάδα και ο linker συνδέει τα αντικείμενα και τις βιβλιοθήκες. Όταν λείπει το αντικείμενο που ορίζει τη συνάρτηση add, η μεταγλώττιση του main.c μπορεί να περάσει αλλά η σύνδεση αποτυγχάνει. Η προσθήκη ενός ακόμη header χωρίς τη σωστή υλοποίηση δεν αρκεί.

Αναπαραγωγή και επιδιόρθωση χωρίς δίκτυο — C11

Αποθήκευσε ως reproduce.sh και εκτέλεσε sh reproduce.sh σε Linux/Termux με διαθέσιμο C compiler. Όλα τα αρχεία δημιουργούνται σε προσωρινό κατάλογο. Η πρώτη σύνδεση αναμένεται να αποτύχει, ενώ η δεύτερη πρέπει να συμπεριλάβει και τις δύο μονάδες και να επιστρέψει κωδικό εξόδου μηδέν.

#!/usr/bin/env sh
set -eu
work=$(mktemp -d)
trap 'rm -rf -- "$work"' EXIT
cat > "$work/main.c" <<'C'
int add(int a, int b);
int main(void) { return add(2, 3) == 5 ? 0 : 1; }
C
cat > "$work/add.c" <<'C'
int add(int a, int b) { return a + b; }
C
if cc -std=c11 -Wall -Wextra -Werror "$work/main.c" -o "$work/broken" 2>"$work/error.log"; then
  echo 'FAIL: missing object was incorrectly linked' >&2
  exit 1
fi
cc -std=c11 -Wall -Wextra -Werror "$work/main.c" "$work/add.c" -o "$work/fixed"
"$work/fixed"
printf 'PASS: missing definition rejected; both translation units linked\n'

Διάγνωση σε μεγαλύτερο πρόγραμμα

Μεταγλώττισε χωριστά με cc -c main.c και cc -c add.c, έπειτα σύνδεσε τα αρχεία αντικειμένων. Όταν η συνάρτηση βρίσκεται σε στατική βιβλιοθήκη, η σειρά των object files και των επιλογών -l μπορεί να επηρεάσει το αποτέλεσμα σε GNU-style linkers. Το nm main.o εμφανίζει συχνά U add για μη επιλυμένο σύμβολο και το nm add.o εμφανίζει T add για υλοποιημένη συνάρτηση. Αν υπάρχει όνομα αλλά αποτυγχάνει η σύνδεση, εξέτασε διαφορά C/C++ linkage, ασυμβατότητα αρχιτεκτονικής και τη βιβλιοθήκη που πραγματικά επιλέχθηκε.

Στοχευμένες ασκήσεις

  1. Αφαίρεσε μόνο το add.c από την επιτυχημένη εντολή και πρόβλεψε σε ποιο στάδιο εμφανίζεται το σφάλμα. Ξεχώρισε ελλιπή δήλωση από ανύπαρκτη υλοποίηση.
  2. Μετονόμασε την υλοποίηση σε sum_values χωρίς να αλλάξεις τη δήλωση και παρατήρησε το σύμβολο που λείπει.
  3. Δημιούργησε στατική βιβλιοθήκη με ar rcs libmathlocal.a add.o και σύγκρινε διαφορετικές θέσεις της βιβλιοθήκης στη γραμμή σύνδεσης, όπου υποστηρίζεται.
  4. Εμφάνισε το αποθηκευμένο error.log πριν καθαριστεί ο δοκιμαστικός κατάλογος. Μην κρύβεις το σφάλμα μέσω αλλαγής των προειδοποιήσεων.

Παραδοτέα: αποτυχία πρώτης σύνδεσης, PASS στο πλήρες πρόγραμμα και εξήγηση της διαφοράς μεταξύ compiler και linker.

Τεκμηρίωση: https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html