0

I've got a function that takes a matrix of velocities for a bunch of particles and tries to calculate the total kinetic energy of the particles.

It doesn't give me the right value. In order to debug, I added a few printf("value: %e \n", energy) in the function.

And now, the return value depends on how many of these printfs I leave uncommented.

double GetKineticEnergy(int dim, int nParticles, double vel[nParticles][dim], double mass)
{
  int i,j;
  double sum;
  double energy = 0;

  for(i=0;i<nParticles;i++) {
    sum = 0;
    for(j=0;j<dim;j++) {
      sum += vel[i][j]*vel[i][j];
    }
    energy += sum*mass/2;
    // printf("energy: %e \n", energy);
  }
  // printf("total: %e \n", energy);
  return(energy);
}

and right after returning to the caller I print the returned value. I get 18.0, 19.0, 21.0, or 24.0, depending on which combination of the printfs I uncomment.

What am I doing wrong?


Update:

In trying to troubleshoot this, I've commented out pretty much everything. The function is reduced to

{
  double energy = 123;
  return(energy);
}

and the main program is

int main() {
  double a;
  double vel[5][5];

  a = GetKineticEnergy(1, 1, vel, 1);
  printf("value: %e \n", a);
}

and I get

value: 0.000000e+00

as output.


Update:

The problem goes away if I hardcode the second dimension of the 2D array double vel[][3]. For the time being, this seems like a useful fix, but I cringe at that type of hardcoding.

gibson
  • 491
  • 1
  • 3
  • 15
  • [I get same answer](http://ideone.com/BGaVJl) for any permutation – Mohit Jain Nov 12 '14 at 12:59
  • I just tried setting ``double energy = 123;``, commenting out the rest of the function except ``return(energy);``, and commenting out everything in the main program except the call and the printout. I get ``0`` instead of ``123`` back. wtf – gibson Nov 12 '14 at 13:01
  • Please show how this function is used in main program. – Martin Nov 12 '14 at 13:02
  • Are you in a multi-threading context ? Perhaps something is messing with your adresses. Toggling comments on `printf` would affect the process timing and generates different results. – n0p Nov 12 '14 at 13:03
  • I don't think I'm multithreading anything. If I am, I'm not doing it on purpose. – gibson Nov 12 '14 at 13:08
  • [It returns correct answer](http://ideone.com/guIAJk). I may sound stupid, but you can try replaing `return(energy);` with `return energy;` – Mohit Jain Nov 12 '14 at 13:08
  • 1
    It can happen if `GetKineticEnergy` function is in a different file and prototype is not available. Consider declaring its prototype in main. – Mohit Jain Nov 12 '14 at 13:11
  • @MohitJain: If the OP asked this without `-Wall -Wextra -Wpedantic`... Ugh. – EOF Nov 12 '14 at 13:15
  • I just realised that I didn't include the .h-file in the main program. Now that I'm trying to do that, I get some type problems with the 2D-array. What should the function declaration say when I'm trying to pass a 2D-array? – gibson Nov 12 '14 at 13:16
  • `double GetKineticEnergy(int dim, int nParticles, double ** vel, double mass)` – n0p Nov 12 '14 at 13:52
  • 1
    @Coconop [no no no no no!](http://stackoverflow.com/a/8767247/1366431) – Leushenko Nov 12 '14 at 15:10
  • @Leushenko ok ok ok ok ok! – n0p Nov 12 '14 at 15:40
  • If you don't want to hard code the multidimensional array and if you are passing in all the dimensions(which you are) then you can declare the array parameter as a pointer to a double (ie. `double *vel`). You can then manually index the array. With the 2D array in your example accessing `vel[i][j]` would be done manually with `vel[i * dim + j]` . – Michael Petch Nov 12 '14 at 16:11

2 Answers2

1

It can happen if GetKineticEnergy function is in a different file and prototype is not available. Consider declaring its prototype in main or include required header file.

Mohit Jain
  • 29,414
  • 8
  • 65
  • 93
0

You have invoked undefined behaviour.

When you are faced with seemingly inexplicable behaviour from a C program, it is typically the result of undefined behaviour. Here are a few potential problems that you should look into:

  • Compiler warnings

    Compilers usually omit many important warning messages by default, and you have to enable those yourself. Compiling with optimizations enabled can also activate some additional warning messages due to the added code analysis. If you're using GCC, you should at a minimum use something like gcc -ansi -pedantic -W -Wall -O2.

  • Function prototypes

    Have you provided correct function declarations (with prototypes) for all the functions in your code? Without a correct declaration of GetKineticEnergy(), the compiler will pass the last argument as int and assume that the return type is int.

    Did you #include <stdio.h>? printf() is a variadic function. Variadic functions usually require different calling conventions than normal functions. Calling a variadic function without the correct prototype causes undefined behaviour.

  • Buffer overflow

    Did you allocate enough memory, or specify a large enough size, for the array passed to the function? Are you passing the correct dimensions? Accessing elements beyond the limits of a buffer can cause perplexing results, especially with optimizations enabled.

Nisse Engström
  • 4,555
  • 22
  • 24
  • 38