Нет предупреждения от gcc, когда определение функции в связанном источнике отличается от прототипа функции в заголовке - PullRequest
1 голос
/ 02 июня 2010

У меня была проблема с частью моего кода, которая после некоторых итераций, казалось, читала NaN как значение double структуры. Я думаю, что нашел ошибку, но все еще задаюсь вопросом, почему gcc (версия 3.2.3 для встроенного Linux с busybox) не предупредил меня. Вот важные части кода:

Файл c и его заголовок для функций получения данных через USB:

// usb_control.h
typedef struct{
    double mean;
    short *values;
} DATA_POINTS;

typedef struct{
    int size;
    DATA_POINTS *channel1;
    //....7 more channels
} DATA_STRUCT;

DATA_STRUCT *create_data_struct(int N);  // N values per channel
int free_data_struct(DATA_STRUCT *data);

int aqcu_data(DATA_STRUCT *data, int N);

Файл c и заголовка с вспомогательной функцией (математика, битовое смещение и т. Д.):

// helper.h
int mean(DATA_STRUCT *data);

// helper.c (this is where the error is obviously)
double mean(DATA_STRUCT *data)
{
    // sum in for loop
    data->channel1->mean = sum/data->N;
    // ...7 more channels
    // a printf here displayed the mean values corretly
}

Основной файл

// main.c
#include "helper.h"
#include "usb_control.h"

// Allocate space for data struct
DATA_STRUCT *data = create_data_struct(N);

// get data for different delays
for (delay = 0; delay < 500; delay += pw){
    acqu_data(data, N);
    mean(data);
    printf("%.2f",data->channel1->mean); // done for all 8 channels
    // printf of the mean values first is correct. Than after 5 iterations
    // it is always NaN for channel1. The other channels are displayed correctly;
}

В основном файле не было ни сбоев, ни каких-либо других ошибок, только NaN для channel1.

После обнаружения ошибки, которая была непростой, ее, конечно, нужно было исправить на восток. Тип возврата mean(){} был неверным в определении. Вместо double mean() это должно быть int mean(), как определяет прототип. Когда все функции помещены в один файл, gcc предупреждает меня о переопределении функции mean(). Но когда я скомпилировал каждый файл c отдельно и связал их, gcc, похоже, упустил это.

Так что мои вопросы будут. Почему я не получил никаких предупреждений, даже не связанных с gcc -Wall? Или есть еще одна скрытая ошибка, которая сейчас не вызывает проблем?

С уважением, христианская

Ответы [ 2 ]

3 голосов
/ 02 июня 2010

Когда каждый .c файл компилируется отдельно, единственная информация, которую знает компилятор, это прототип функции, который вы дали.

Поскольку каждый файл компилируется отдельно, процесс компиляции main.c никак не может определить, что определение mean в helper.c неверно.

После компиляции файла .c подпись будет удалена, поэтому компоновщик также не сможет узнать, что mean также неверен.

Простое исправление всегда включает файл интерфейса .h в реализацию .c файл

// in helper.c:
#include "helper.h"
double mean(DATA_STRUCT *data);

Тогда процесс компиляции helper.c заметит этот несовместимый тип и предупредит вас.

0 голосов
/ 02 июня 2010

Среднее значение обычно является реальным значением, поэтому double - это нормально. Здесь вы определяете mean как возвращающий double, но прототип говорит int mean(...).

Единственный способ, которым gcc может знать о том, что существует переопределение, - это если переопределение происходит по-настоящему ... Когда вы компилируете файлы отдельно, вероятно, отсутствует средний прототип ... он не отображается в вашем фрагменте кода по крайней мере: вы должны включить helper.h также в helper.c. При этом gcc -c helper.c должен предупредить вас. У меня gcc 4.3.2, но я почти уверен, что так должно быть и для вашей версии. В основном вы просто используете mean, поэтому здесь gcc доверяет , что сказано в helper.h. Когда вы ссылаетесь, больше нет информации о размере аргументов и возвращаемом значении, и происходят плохие вещи (например, чтение int как двойного).

Еще одна деталь: вы говорите, что получаете NaN для int структуры ... ну, в структуре есть двойное число, и int не может быть NaN!

...