DedSec Project

implicit declaration of function — DedSec Project

C implicit declaration — σωστή δήλωση πριν από την κλήση Τι σημαίνει το διαγνωστικό Η C11 απαιτεί ορατή δήλωση μιας συνάρτησης πριν από την κλήση της. Δεν πρόκειται για σφάλμα linker: ο…

C implicit declaration — σωστή δήλωση πριν από την κλήση

Τι σημαίνει το διαγνωστικό

Η C11 απαιτεί ορατή δήλωση μιας συνάρτησης πριν από την κλήση της. Δεν πρόκειται για σφάλμα linker: ο μεταγλωττιστής δεν γνωρίζει την ακριβή υπογραφή και σε παλιές διαλέκτους μπορεί να υποτεθεί λανθασμένος τύπος επιστροφής ή τρόπος μεταφοράς παραμέτρων. Για συναρτήσεις της τυπικής βιβλιοθήκης συμπερίλαβε το επίσημο header, όχι μία επινοημένη δήλωση. Η strlen δηλώνεται στο string.h και όχι στο stdio.h.

Αναπαραγωγή και σωστή διόρθωση

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

#!/usr/bin/env sh
set -eu
work=$(mktemp -d)
trap 'rm -rf -- "$work"' EXIT
cat > "$work/broken.c" <<'C'
#include <stdio.h>
int main(void) {
    printf("%zu\n", strlen("Ada"));
    return 0;
}
C
if cc -std=c11 -Wall -Wextra -Werror=implicit-function-declaration "$work/broken.c" -o "$work/broken" 2>"$work/error.log"; then
  echo 'FAIL: call without prototype was not diagnosed' >&2
  exit 1
fi
{ printf '#include <string.h>\n'; cat "$work/broken.c"; } > "$work/fixed.c"
cc -std=c11 -Wall -Wextra -Werror "$work/fixed.c" -o "$work/fixed"
output=$("$work/fixed")
test "$output" = '3'
printf 'PASS: missing declaration rejected; correct header restored\n'

Γιατί δεν αρκεί να κρύψουμε την προειδοποίηση

Η απενεργοποίηση της προειδοποίησης δεν αποκαθιστά τον πραγματικό τύπο επιστροφής ούτε τη μετατροπή των ορισμάτων. Σε συστήματα 64 bit, η εσφαλμένη αντιμετώπιση δείκτη σαν int μπορεί να καταστρέψει διεύθυνση μνήμης. Για δική σου συνάρτηση δημιούργησε κοινό header και συμπερίλαβέ το τόσο στον caller όσο και στο αρχείο υλοποίησης. Για εξωτερική βιβλιοθήκη έλεγξε χωριστά το πακέτο που παρέχει τη δήλωση και το αντικείμενο που προσφέρει την υλοποίηση.

Διαδοχικές ασκήσεις διάγνωσης

  1. Σύγκρινε το σφάλμα με το undefined reference. Σε ποιο στάδιο κατασκευής εμφανίζεται το καθένα;
  2. Αντικατάστησε τη strlen με δική σου συνάρτηση και γράψε header με τη σωστή δήλωση. Άλλαξε έναν τύπο παραμέτρου και έλεγξε το διαγνωστικό.
  3. Δούλεψε με τη διάλεκτο C του έργου και κατάγραψε εκδόσεις GCC ή Clang και επιλογές ελέγχου. Μη στηρίζεσαι στις παλιές, ελαστικές παραδοχές πριν από τη C99.
  4. Σε Android cross-compilation έλεγξε ότι τα headers και οι βιβλιοθήκες είναι για τον σωστό στόχο. Μην αντιγράφεις τυχαία headers από άλλο λειτουργικό.

Παραδοτέα: απορριφθείσα μεταγλώττιση, επιτυχημένη διόρθωση με έξοδο 3 και τεκμηριωμένος κανόνας δήλωσης των δικών σου συναρτήσεων.

Πηγή: https://en.cppreference.com/w/c/string/byte/strlen.html