0

I have written this code for a sampling assignment at my university.

#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char **argv){
    struct timeval tv;

    float t = atoi(argv[1]);  //sampling time period in sec's
    float dt = atoi(argv[2]);   //sampling rate in msec's
    double time;
    int nsamples = t/dt * 1000; //number of samples floored

    //samples storage array
    double *samples;
    samples = malloc(nsamples);

    printf("%d\n\n",nsamples);

    int c = 0;  //array index
    double divergance;

    gettimeofday(&tv, NULL);
    time =(double) tv.tv_sec + tv.tv_usec / 1000000.0f;
    samples[c] = time;
    printf("time: %f\n", samples[c]);

    usleep(dt * 1000);

    while(c<nsamples){
      c++;

      gettimeofday(&tv, NULL);
      time = (double) tv.tv_sec + tv.tv_usec / 1000000.0f;
      samples[c] = time;

      //divergance calculated in msec's
      divergance = (samples[c] - samples[c-1]);
      if (c==9){
        printf("%f \n \n%f", samples[c-1], samples[c]);
      }
      printf("time: %f\ndivergance: %f ms\n\n", samples[c], divergance*1000);

      usleep(dt *1000);
    }

}

and this is my output

time: 1557335682.435666 divergance: 200.127125 ms

time: 1557335682.635813 divergance: 200.146914 ms

time: 1557335682.835952 divergance: 200.139046 ms

time: 1557335683.036075 divergance: 200.123072 ms

time: 1557335683.236192 divergance: -50328976507548121002151598324465532616014103321089770750300716493231241208217866953937760599346823570331739493744117764925654540012842402655523878795775819489233146901362588461216017208320541658368563434403808909221817741213696.000000 ms

time: 1557335683.436400 divergance: 1557335683436.399902 ms

time: 1557335683.636521 divergance: 1557335683636.520752 ms

time: 1557335683.836647 divergance: 1557335683836.646973 ms

Does anyone understand what's that weird output there on the fifth calculation. I can not imagine any logical explanation as I have not encountered any similar "bug" before. Does it have to do with some certain feature of gettimeofday() function?

Νote: the input is 10 and 200

Giannis
  • 75
  • 9
  • You have `while(c – Weather Vane May 08 '19 at 17:32
  • 4
    `samples = malloc(nsamples)` --> `samples = malloc(nsamples * sizeof(*samples))` – dbush May 08 '19 at 17:34
  • @dbush thank you very much. it worked. could you explain why? – Giannis May 08 '19 at 17:37
  • @GiannisGonidelis I've added an answer detailing this. – dbush May 08 '19 at 17:44
  • The time that gets printed is correct, so the problem is apparently not related to gettimeofday. – user253751 May 08 '19 at 22:57
  • Sorry, why do you mix `float` with `double` floating point values? Do you fear of running out of stack space on declaring two `float` variables instead of declaring them `double`? If you are trying to save stack space, probably you have not got that you are making the compiler to consider a large amount of automatic conversions from `double` to `float` and viceversa. And worse, loss of precision when truncating values. – Luis Colorado May 12 '19 at 10:55

2 Answers2

3

You haven't allocated enough space for samples:

samples = malloc(nsamples);

The malloc function allocates space for the specified number of bytes, not the number of array elements. So your array is much shorter that you think it is. This means you'll eventually write past the end of the array, invoking undefined behavior.

You need to multiply the number of elements by the element size to allocate the correct amount of space:

samples = malloc(nsamples * sizeof(*samples));

You also have an off-by-one error when accessing the array:

int c = 0;
...
while(c<nsamples){
  c++;
  ...
  samples[c] = time;
  ...
}

This will also write past the end of the array, specifically one array element too many.

Change the loop to start with the value 1 and increment at the end.

int c = 0;
...
c = 1;
while(c<nsamples){
  ...
  samples[c] = time;
  ...
  c++;
}
dbush
  • 205,898
  • 23
  • 218
  • 273
0

The parameter to malloc(3) mus be the number of bytes to allocate, not the number of samples. If you plan to allocate an array of float or double samples, you had better to multiply that number by the sizeof (float) (or sizeof (double)) before passing the parameter to malloc(3). As samples is defined as a pointer to double, then you should use:

samples = malloc(nsamples * sizeof(double));

or better (if you happen to change the declaration of samples):

samples = malloc(nsamples * sizeof *samples);
Luis Colorado
  • 10,974
  • 1
  • 16
  • 31