views:

68

answers:

2

Hi,

I had a problem with a part of my code, which after some iterations seemed to read NaN as value of a double of a struct. I think I found the error, but am still wondering why gcc (version 3.2.3 on a embedded Linux with busybox) did not warn me. Here are the important parts of the code:

A c file and its header for functions to acquire data over 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);

A c and header file with helper function (math, bitshift,etc...):

// 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
}

The main file

// 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;
}

There were no segfaults nor any other missbehavior, just the NaN for channel1 in the main file.

After finding the error, which was not easy, it was of course east to fix. The return type of mean(){} was wrong in the definition. Instead of double mean() it has to be int mean() as the prototype defines. When all the functions are put into one file, gcc warns me that there is a redefinition of the function mean(). But as I compile each c file seperately and link them afterwards gcc seems to miss that.

So my questions would be. Why didn't I get any warnings, even non with gcc -Wall? Or is there still another error hidden which is just not causing problems now?

Regards, christian

+3  A: 

When each .c file is compiled separately, the only information the compiler knows is the function prototype you have given.

Because every file is compiled separately, there is no way the compiler process of main.c knows the definition of mean in helper.c is wrong.

After the .c file is compiled, the signature will be stripped, so the linker cannot know the mean is wrong either.

A simple fix is always include the interface .h file in the implementation .c file

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

Then the compiler process of helper.c will notice that inconsistent type and warn you.

KennyTM
Thanks! Simple but effective.
c_c
A: 

A mean usually is a real value so double is ok. Here you define mean as returning double, but the prototype says int mean(...).

The only way gcc can be aware of the fact that there's a redefinition, is if the redefinition occurs for real... When you compile files separately likely the mean prototype is missing... it is not shown in your code fragment at least: you should include helper.h also into helper.c. Doing so, gcc -c helper.c must give you a warning. I have gcc 4.3.2, but I am almost sure it must be so also for the version you have. In the main, you just use mean, so here the gcc trusts what is said in helper.h. When you link, there is no more information about the size of arguments and returning value, and bad things happen (like reading an int as a double).

Another detail: you say you get NaN for an int of the struct... well, in the struct there's a double, and int can't be NaN!

ShinTakezou
The function `mean()` does not return the mean value. It is stored in the data_struct. That's not clear from my code snippet. But I think I wanted the function to return the mean value at first and then forgot to change it...
c_c
ok:D so void or int could do the job according to the use of mean()
ShinTakezou