EXC_BAD_ACCESS when calling Fortran function from C - c

I've looked around, and though there are a lot of EXC_BAD_ACCESS issues, none of them helped.
I'm using Mountain Lion (OSX 10.8 I think?), and PGI 12.
I can't seem to call fortran functions from C, I've written a simplified case and it seems that I can't pass integers.
My fortran function is:
1 integer function smallFortran(a) result(res) bind(c,name='smallFortran_')
2 !integer function smallFortran(a) result(res)
3
4 use ISO_C_BINDING
5 implicit none
6
7 integer(kind=c_int), intent(IN) :: a
8 !integer, intent(IN) :: a
9
10 print *,'A = ', a
11 res = a;
12
13 endfunction smallFortran
And my C function is,
int main() {
int ier=7;
ier = smallFortran_(8);
}
Build it..
matt#pontus:diffFst$ make
pgcc -c cDoDiffFst.c
PGC-W-0267-#warning -- "Unsupported compiler detected" (/usr/include/sys/cdefs.h: 81)
PGC/x86-64 OSX 12.9-0: compilation completed with warnings
pgcc -g -O0 -traceback -o cDoDiffFst cDoDiffFst.o smallFortran.o -lpgf90 -lpghpf2 -lpgf90rtl -lpgftnrtl -lpghpf_rpm
(I hope that warning isn't what's causing my problems, the PGI user forum responds to this by saying they'll send a newer version of the file, but I haven't been replied to yet. And no idea why PGI requires so many extra libraries to be specified)
When I run it in the debugger..
matt#pontus:diffFst$ gdb cDoDiffFst
(gdb) run
Starting program: /Users/matt/aurams/trunk/utils/diffFst/cDoDiffFst
Reading symbols for shared libraries +............................. done
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000008
0x0000000100001906 in _smallFortran_ (a=Cannot access memory at address 0x8
) at smallFortran.f90:10
10 print *,'A = ', a
(gdb)
I'm totally lost, why can't I send an int? I've tried assigning a value to an integer and sending it, no dice. I've tried it as a subroutine, I've tried it without a return value.. nothing works.

Here is an alternative solution that shows how to write Fortran to match the original C of the question. The key is the value qualifier on the declaration. With the Fortran ISO C Binding you match various ways C passes arguments. You can also do away with underscores in routine names ... that's a purpose of the name keyword of bind.
The C code without the underscore in the call:
int main() {
int ier=7;
ier = smallFortran (8);
}
and the matching Fortran:
function smallFortran(a) result(res) bind(c,name='smallFortran')
use ISO_C_BINDING
implicit none
integer(kind=c_int), intent(IN), value :: a
integer(kind=c_int) :: res
print *,'A = ', a
res = a;
endfunction smallFortran

The error should make clear what's going wrong; smallFortran_ expects its argument to be passed by reference (as are all arguments in fortran -- note that I'm being slightly fast and loose here), and tries to access the data at the pointer 8, which fails. Fix is easy; the function expects a pointer, so give it one:
int main() {
int ier = 7;
int arg = 8;
ier = smallFortran_(&arg);
}
This assumes that the fortran integer type corresponds to a C int with the compilers in question; you may need to make arg a long otherwise.

Related

Fortran interop with C function pointer wrong results

I have a C program that calls a Fortran subroutine in a static lib. This subroutine takes as argument a function pointer to a callback implemented in C. A minimal example looks like this:
Fortran code:
subroutine fortran_function(input, c_function) bind(c)
use, intrinsic :: iso_c_binding
implicit none
real(c_float), value, intent(IN) :: input
type(c_funptr), intent(IN), value :: c_function
abstract interface
subroutine callback(a, b) bind(c)
USE iso_c_binding, only: c_float, c_int
integer(c_int), intent(IN), value :: a
real(c_float), intent(IN), value :: b
end subroutine callback
end interface
procedure(callback), pointer :: c_proc
call c_f_procpointer(c_function, c_proc)
call c_proc(1_c_int, input)
if (input > 1.0) call c_proc(2_c_int, input)
end subroutine fortran_function
C code:
#include <stdio.h>
typedef void (*c_function)(int, float);
void fortran_function(float, c_function);
void callback(int a, float b)
{
printf("a=%d, b=%.1f\n", a, b);
}
int main()
{
fortran_function(0.0, &callback);
fortran_function(5.0, &callback);
}
If I compile this (Intel and MSVS on Windows) everything works fine and I get the expected output:
a=1, b=0.0
a=1, b=5.0
a=2, b=5.0
However, I ultimatley want to target a powerpc (using gfortran and gcc-variant crosscompiler). The program compiles there without warnings (-Wall) but produces the output:
a=1, b=0.0
a=2, b=0.0
a=1, b=5.0
a=2, b=5.0
This is very strange because for the first call the flow should never enter the if-body. Apparently it does so anyway, but even prints the correct value for the input.
Compiled on Ubuntu with:
powerpc-linux-gnu-gfortran test.f90 -c -Wall -pedantic
ar cr test.lib test.o
What I already checked:
Replacing if (input > 1.0) with if (input > 1.0_c_float) doesn't solve the problem
Using pass-by-reference instead by-value on the function pointer crashes instantly (on Windows it runs fine)
Turning of optimization (on both the C and Fortran part) doesn't solve the problem
All types are 4 byte sizeof(real)=sizeof(real(c_float))=sizeof(integer)=sizeof(integer(c_int)) (same in C)
Does anyone have an idea what could possibly cause this problem?

OCaml return unboxed float from C function with bytecode compiler

I have a very simple function that calls time(2) in order to get the epoch time and returns it as an unboxed OCaml float.
The platform here is OS X 10.12.6 and I've tested using OCaml versions 4.03.0 and 4.04.0 .
Here is libunixtime.c
#define CAML_NAME_SPACE
#include <time.h>
#include <caml/memory.h>
#define IGNORE_UNUSED(x) ( (void)(x) )
CAMLprim double
ocaml_unixtime(value unit)
{
IGNORE_UNUSED(unit);
return (double) time(NULL);
}
The OCaml code, unixtime.ml looks like this ... it returns an unboxed float and indicates to the compiler that it doesn't perform any OCaml-side allocations.
This function takes less than 5 arguments, so it seems like implementing it once and using that for both the byte code compiler and native compiler should be fine (https://caml.inria.fr/pub/docs/manual-ocaml/intfc.html#sec397).
external unixtime : unit -> (float [#unboxed]) =
"ocaml_unixtime" "ocaml_unixtime" [##noalloc];;
let () = Printf.printf "%f\n" (unixtime ())
This example works fine with the native compiler (although I'm a little concerned that the cast to double is not exactly the right thing to do but It Works On My Machine).
% ocamlopt unixtime.ml libunixtime.c
% ./a.out
1506195346.000000
However, when compiling with the bytecode compiler and attempting to run, I get a segfault immediately.
% ocamlc -custom unixtime.ml libunixtime.c
% ./a.out
Segmentation fault
Exit 139
Does the bytecode compiler not support unboxed floats? How do I figure out why the behavior differs between the bytecode and native compilers?
First, your code seems to be missing a CAMLparam call for the unit value. This is necessary so that the GC knows about it, see section 19.1.
But there's another more important bug: the bytecode version cannot use unboxed functions (section 19.10), so you'll have to provide an alternative implementation for the bytecode compiler that returns a boxed value using caml_copy_double and CAMLreturn.

C - Variadic function compiles but gives segmentation fault

I have a variadic function in C to write in a log file, but as soon as it is invoked, it gives a segmentation fault in the header.
In the main process, the call has this format:
mqbLog("LOG_INFORMATION",0,0,"Connect",0,"","Parameter received");
and the function is defined this way:
void mqbLog(char *type,
int numContext,
double sec,
char *service,
int sizeData,
char *data,
char *fmt,
...
)
{
//write the log in the archive
}
It compiles OK. When I debug the process, the call to the mqbLog function is done, and it gives me the segmentation fault in the open bracket of the function, so I can ask about the function values:
(gdb) p type
$1 = 0x40205e "LOG_INFORMATION"
(gdb) p numContext
$2 = 0
(gdb) p sec
$3 = 0
(gdb) p service
$4 = 0x0
(gdb) p sizeData
$5 = 4202649
(gdb) p data
$6 = 0x0
Any ideas will be gratefully received.
Based on the gdb output, it looks like the caller didn't have a prototype for the function it was calling. As #JonathanLeffler noticed, you wrote 0 instead of 0.0, so it's passing an integer where the callee is expecting a double.
Judging from the pointer value, this is probably on x86-64 Linux with the System V calling convention, where the register assigned for an arg is determined by it being e.g. the third integer arg. (See the x86 wiki for ABI/calling convention docs).
So if the caller and callee disagree about the function signature, they will disagree about which arg goes in which register, which I think explains why gdb is showing args that don't match the caller.
In this case, the caller puts "Connect" (the address) in RCX, because it's the 4th integer/pointer arg with that implicit declaration.
The caller looks for the value of service in RDX, because its caller's 3rd integer/pointer arg.
sec is 0.0 in the callee apparently by chance. It's just using whatever was sitting in XMM0. Or maybe possibly uninitialized stack space, since the caller would have set AL=0 to indicate that no FP args were passed in registers (necessary for variadic functions only). Note al = number of fp register args includes the fixed non-variadic args when the prototype is available. Compiling your call with the prototype available includes a mov eax, 1 before the call. See the source+asm for compiling with/without the prototype on the Godbolt compiler explorer.
In a different calling convention (e.g. -m32 with stack args), things would break at least a badly because those args would be passed on the stack, but int and double are different sizes.
Writing 0.0 for the FP args would make the implicit declaration match the definition. But don't do this, it's still a terrible idea to call undeclared functions. Use -Wall to have the compiler tell you when your code does bad things.
You function might still crash; who knows what other bugs you have in code that's not shown?
When your code crashes, you should look at the asm instruction it crashed on to figure out which pointer was bad — e.g. run disas in gdb. Even if you don't understand it yourself, including that in a debugging-help question (along with register values) can help a lot.

Weird behavior while doing C programming in eclipse [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have not touched C for long really long time. My first language was C. But then we have been taught C++, Java and C# (in college days). Now mostly my work involve Java and groovy. And suddenly I have to do C again. I am not familiar with how industry uses C as I never was in project doing stuff in C.
I started in eclipse CDT, with MinGW on Windows 10. My new program grew big quickly. And my lack of experience was unrevealed to me. When I run, my program used to crash showing Windows dialog saying "MyProgram.exe has stopped working". Now I had no clue whats going wrong. Compilation was clean with no error, but only one warning. Now since from Java world, I was like warnings are not that fatal. So I simply just ignored it (I thats my lack of C experience). And went on debugging found the cause. Realised that the warning was indeed about the cause. Suffered mental frustation of wasting hours in debugging.
So here is code replicating issue in my original code:
1 #include "stdio.h"
2 #include "limits.h"
3
4 typedef struct TempStruct TempStruct;
5
6 struct TempStruct
7 {
8 int a;
9 TempStruct *next;
10 };
11
12 int function1(TempStruct *param)
13 {
14 return param == NULL;
15 }
16
17 int function2(TempStruct **param)
18 {
19 if(function1(param))
20 {
21 return INT_MIN;
22 }
23 *param = (*param)->next;
24 return 0;
25 }
26
27 int main()
28 {
29 TempStruct *tempStructObj = NULL;
30 function2(&tempStructObj);
31 printf("Does not reach here!!!");
32 return 0;
33 }
My C-noob eyes did not see anything wrong in it. Good that I knew how to do debugging. I got following in debugging:
In main() this is done: *tempStructObj = NULL. So, I was expecting function1() to return 1, making function2() returning from line 21.
The issue was that function1() takes TempStruct*. But on line 19, I passed it **param. So inside function1(), param wasnt NULL. So it returned false (0 I guess). So function2() did not returned from line 21. It executed (*param)->next and hence the program crashed.
My questions:
Q1. Shouldn't be such issue be reported as Error's instead of Warnings? Is there any setting which can report such potentially fatal warnings to error?
Q2. Does eclipse logs the reasons of such sudden app crash somewhere? So instead of debugging by stepping through each line, I can simply refer to the report which can possibly specify the line number which caused the crash
Q3. What is industry-standard approach to deal with such mistakes? Of course one will say dont commit the mistake. But I am asking about precautions that are taken to avoid such mistakes or auto detect them. Like above I asked about settings to make eclipse report the issue as fatal one or making crashes to generate report so that stuff can be fixed quickly instead of hours long debuggins. Do you use any better (and possibly involving smaller learning curve) alternative to (eclipse CDT + MinGW + Windows) that will provide more powerful debugging so that I can avoid such errors.
Q4. In point 1 of above diagram, what is that Error: Multiple errors reported.... This stuff occurred occasionally, but not always, say once in 5 debugging sessions. What can be the reason behind such ad hoc behavior?
Q5. In point 3 of above diagram, what is that (0x62ff2c) value of param inside function1()? If I keep signature of function1() correctly as int function1(TempStruct **param) and change inside reference correctly to *param, *param is correctly 0x0 (i.e. NULL):
Edit
This on Ideone works (with C) & prints "Does not reach here!!!". So dont know how it handled (*param)->next.
This on ideone (with C99 Strict) does gives error (not warning).
Q1. No, they are warnings as they are legit C code. It could be possible that you want such code. You can use -Werror on gcc to make warnings to errors. Also add some other flags for turning on more warnings like -Wall -Wpedantic -Wextra -Wshadow -Wconversion -Wno-sign-compare etc. This'd be a bit closer to what you're probably used to when using Java ;-)
Q2. Atleast on Linux you have coredumps, iirc Windows was minidumps. These can be loaded together with the corresponding executable into a debugger. Then you can access backtraces, values etc.
Q3.
Like above I asked about settings to make eclipse report the issue as fatal one or making crashes to generate report so that stuff can be fixed quickly instead of hours long debuggins.
Log yourself. Also there can be macros for easing this.
Do you use any better (and possibly involving smaller learning curve) alternative to (eclipse CDT + MinGW + Windows) that will provide more powerful debugging so that I can avoid such errors.
IDE is pretty irrelevant for C imho. Use Linux with native GCC instead, MinGW is nice but it can be daunting (my experience).
Ofcourse MS VSC++ can also compile C but its just for C++ compatible thus not really specific to one standard.
Q4. Well, multiple errors occured which are listed. If it's difficult to reproduce it might be a problem in your setup, this is exactly the experience I had with MinGW on Windows.
Q5. It's the address -- you have a pointer to a pointer, so the first ("outer") pointer is that address, pointing to another pointer which is NULL.
Or more verbosely:
tempStructObj is a pointer to NULL (ie. an int_ptr which holds the value 0x0.
To function2 you pass another int_ptr which holds the semi-random value/address of the automatic variable int_ptr tempStructObj is stored
Ie. you have such:
Address &tempStructObj: tempStructObj
in the RAM.
When you then call function1, you pass the value of this (not-NULL) pointer. Of course the comparison is thus always false.
You'd need to compare
*param with NULL.
Even more:
If you compile with GCC (on Linux) and use really verbose flags you get:
gcc -std=c99 -Wall -Wpedantic -Wextra -Wshadow -Wconversion -Wno-sign-compare -o main main.c
main.c: In function ‘function2’:
main.c:19:18: warning: passing argument 1 of ‘function1’ from incompatible pointer type [-Wincompatible-pointer-types]
if(function1(param))
^
main.c:12:5: note: expected ‘TempStruct * {aka struct TempStruct *}’ but argument is of type ‘TempStruct ** {aka struct TempStruct **}’
int function1(TempStruct *param)
^
So exactly the problem you had ^^
Also I'd remove the function1 altogether, it's completely unnecessary and just obfuscates the code. Also I'd use a different name for the struct and the typedef, appending the latter with a _t. Also I'd move it into one shorter piece of code.
On a side note: add a \n in the printf()-call.
Edited code:
#include <stdio.h>
#include <limits.h>
typedef struct TempStruct_s {
int a;
struct TempStruct_s *next;
} TempStruct_t;
int function(TempStruct_t **param)
{
if(!*param) {
return INT_MIN;
}
*param = (*param)->next;
return 0;
}
int main()
{
TempStruct_t *tempStructObj = NULL;
function(&tempStructObj);
printf("Does not reach here!!!\n");
return 0;
}
When you
TempStruct *tempStructObj = NULL;
function2(&tempStructObj);
you are sending into function2 the address of your variable tempStructObj (0x62ff2c). When doing
if(function1(param)){
return INT_MIN;
}
you're sending the same address (0x62ff2c). Therefore, param == NULL is false.
Q5: if you use the proper signature, as you suggest, then you check the value that tempStructObj is pointing at, which is what you want, and everything works.
The error you get about not being able to access memory 0x4 is due to your structure and wrong null checking. (*param)->next is expected work on a memory zone with an int and another pointer. However, *param is pointing at address 0x0, so the int is at address 0x0 and the next pointer is at address 0x4, hence the error.

No output from a Fortran program using the Gnu Scientific Library via a c wrapper

I'm trying to write a wrapper to use the gsl library with Fortran. I have managed to get a simple wrapper to work - the example from http://www.helsinki.fi/~fyl_tlpk/luento/ohj-13-GSL-e.html
Fortran code
program gsltest
implicit none
real(kind=selected_real_kind(12)) :: a = 0.11, res
external :: glsgateway
call gslgateway(a,res)
write(*,*) 'x', a, 'atanh(x)', res
end program gsltest
c function
#include <gsl/gsl_math.h>
void gslgateway_(double *x, double *res){
*res = gsl_atanh(*x);
}
That's all well and good. However, I'm having problems with a more complicated wrapper. I have the following code modified from an example at http://apwillis.staff.shef.ac.uk/aco/freesoftware.html
c wrapper (rng_initialise.c)
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
static gsl_rng* r;
void rng_initialise__(int* s) {
r = gsl_rng_alloc(gsl_rng_taus);
gsl_rng_set(r, (unsigned long int)(*s));
}
Fortran main (main.f90)
PROGRAM main
integer seed
call system_clock(seed)
WRITE (*,*) 'calling rng_initialise'
call rng_initialise(seed)
END PROGRAM main
which I then compile and link by
gcc -c rng_initialise.c
g95 -c main.f90
g95 -o main main.o rng_initialise.o -L/usr/libs -lgsl
When I run this program, I get no output. However, if I comment out the lines inside rng_initialise
...
void rng_initialise__(int* s) {
// r = gsl_rng_alloc(gsl_rng_taus);
// gsl_rng_set(r, (unsigned long int)(*s));
}
then I get output from the Fortran code (it writes 'calling_rng_initialise' to STDOUT).
So, the problem seems to be the calls to gsl_rng_alloc and gsl_rng_set. But I don't get any error messages, and I don't know why they would prevent the Fortran code from doing anything. Any ideas?
As already suggested, the best way to do this is to use the Fortran ISO C Binding because it will instruct Fortran to use the C calling conventions to match the C routines of the GSL library. The ISO C Binding is part of the Fortran 2003 standard and has been available in many Fortran 95 compilers for several years. As part of the standard it makes interfacing Fortran and C, in both directions, portable and much easier than the OS and compiler dependent hacks that used to be necessary. I recommend ignoring instructions that pre-date the ISO C Binding as obsolete.
Generally you won't need to write any C wrapper code to call the GSL library, only Fortran specifications statements to describe the C routine interfaces to Fortran in Fortran syntax. Here is a simple example that calls the GSL routine gsl_cdf_chisq_Q
program cum_chisq_prob
use iso_c_binding
interface GSL_CummulativeChiSq_Prob_Upper
function gsl_cdf_chisq_Q ( x, nu ) bind ( C, name="gsl_cdf_chisq_Q" )
import
real (kind=c_double) :: gsl_cdf_chisq_Q
real (kind=c_double), VALUE, intent (in) :: x
real (kind=c_double), VALUE, intent (in) :: nu
end function gsl_cdf_chisq_Q
end interface GSL_CummulativeChiSq_Prob_Upper
real (kind=c_double) :: chisq_value
real (kind=c_double) :: DoF
real (kind=c_double) :: Upper_Tail_Prob
write ( *, '( / "Calculates cumulative upper-tail probability for Chi-Square distribution." )' )
write ( *, '( "Input Chisq Value, Degrees of Freedom: " )', advance='no' )
read ( *, * ) chisq_value, DoF
Upper_Tail_Prob = gsl_cdf_chisq_Q ( chisq_value, DoF )
write ( *, '( "Probability is:", 1PG17.10 )' ) Upper_Tail_Prob
stop
end program cum_chisq_prob
Even easier: you can find a pre-written library to allow you to call GSL from Fortran at http://www.lrz.de/services/software/mathematik/gsl/fortran/
Most likely you have the linkage between the two routines wrong in some way. If the stack isn't dealt with correctly when you hop through that interface, dang near anything can happen.
I'm not noticing any code on either the Fortran side or the C side specifying the other's calling convention. I'm not an expert with Gnu Fortran, but I know most compilers will require some kind of note that they should be using another compiler's calling convention, or Bad Things may happen.
With just a little web searching, I see that the G95 Fortran manual (PDF) has a nice long section titled "Interfacing with G95 Programs", that appears to go into this in detail. Just from skimming, it looks like you should be using the BIND(C) attribute on your Fortran function declaration for that C routine.
The problem is with the static gsl_rng* r; defined in your C file. But I do not know/understand why the standard does not allow this. After studying the source file of the fgsl package a little bit, I found a tweak that works. The fortran file random_f.f90
module fgsl
use, intrinsic :: iso_c_binding
implicit none
type, bind(C) :: fgsl_rng_type
type(c_ptr) :: gsl_rng_type_ptr = c_null_ptr
end type fgsl_rng_type
type, bind(C) :: fgsl_rng
type(c_ptr) :: gsl_rng_ptr = c_null_ptr
end type fgsl_rng
end module fgsl
PROGRAM call_fgsl_rndm
use, intrinsic :: iso_c_binding
use fgsl
implicit none
interface
subroutine srndm(seed, t, r) bind(C)
import
integer(C_INT) :: seed
type(fgsl_rng) :: r
type(fgsl_rng_type) :: t
end subroutine srndm
function rndm(r) bind(C)
import
real(C_DOUBLE) :: rndm
type(fgsl_rng) :: r
end function rndm
end interface
type(fgsl_rng) :: r
type(fgsl_rng_type) :: t
integer(C_INT) :: seed
real(C_DOUBLE) :: xi
seed = 1
call srndm(seed, t, r)
xi = rndm(r)
print *, xi
xi = rndm(r)
print *, xi
xi = rndm(r)
print *, xi
END PROGRAM
and the C file random_c.c
#include <gsl/gsl_rng.h>
typedef struct{
gsl_rng *gsl_rng_ptr;
} fgsl_rng;
typedef struct{
gsl_rng_type *gsl_rng_type_ptr;
} fgsl_rng_type;
void srndm(int *seed, fgsl_rng_type* t, fgsl_rng* r) {
t->gsl_rng_type_ptr = (gsl_rng_type *) gsl_rng_mt19937; // cast to remove the const qualifier
r->gsl_rng_ptr = gsl_rng_alloc(gsl_rng_mt19937);
gsl_rng_set(r->gsl_rng_ptr, *seed);
}
double rndm(fgsl_rng* r) {
return gsl_rng_uniform(r->gsl_rng_ptr);
}
Although only the pointers in the structures are used, the introduction of fgsl_rng and fgsl_rng_type is necessary. Otherwise, the program will fail. Unfortunately, I still have no clear idea why it has to work this way.

Resources