Assuming that every source c file using a variable initialized in a C header file is declared using extern, that variable should be only allocated once no matter how many times a function defined in a source c file including that header and declaring that variable with extern is called.

So I'm referring to one way to ensure that constants used between functions defined in separate files are not allocated for every call to any function that uses that constant.

Now when i call a function in a header file under these conditions using the Haskell FFI, I would like to know if calling functions declared in that header file allocates that variable repeatedly or if it's allocated once. And if its not allocated only once, are there any simple ways to make sure it is?

Here's an example of the .hs, .h, and .c files.

Main.hs:

{-# LANGUAGE ForeignFunctionInterface #-}

module Main (main) where

foreign import ccall unsafe "cstuff.h cfnc"
  cfnc :: IO ()

main :: IO ()
main = do cfnc
          cfnc 
          cfnc

cstuff.h:

extern int myvar; 
void cfnc();

cstuff.c:

#include "cstuff.h"
#include <stdio.h>

int myvar = 1;
void cfnc() {
   printf("%i\n",myvar);
} 

So in this case cfnc was called was called 3 times and I would like to know if myvar is only allocated once or 3 times. And if its not only once what can i do to make sure it's only allocated once?

1

There are 1 best solutions below

0
On BEST ANSWER

Depending on exactly what you mean by allocated, it may in fact be allocated zero times! Check it out:

% objdump -t Main | grep myvar
00000000004a8418 g     O .data  0000000000000004              myvar

That 00000000004a8418 is the address that's been set aside, once and for all before the program even starts, to hold myvar. (The 0000000000000004 is how many bytes have been set aside -- just right for an int on my machine.) Here's evidence (though not proof) that's what it means. Changing cfnc to be

void cfnc() {
   printf("%i\n%p\n",myvar,&myvar);
}

the new output I get from running your program is:

1
0x4a8418
1
0x4a8418
1
0x4a8418

As you say, this is only evidence, not proof -- e.g. perhaps the compiler has done something clever. But no; not only did I run the compiler without optimizations turned on, this is also just the bog-standard thing that every C compiler I know of does for top-level variables.