comp.lang.ada
 help / color / mirror / Atom feed
* generic provokes segmentation fault
@ 2020-05-17 14:19 hreba
  2020-05-17 17:51 ` Dennis Lee Bieber
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: hreba @ 2020-05-17 14:19 UTC (permalink / raw)


Hi,

I'll try to describe the problem without posting loads of code. Still 
working on my thick binding of GSL/Odeiv2, the API of my package odeiv2 
consists of 3 procedures:
  - Init_Solve
  - Solve
  - Finit_solve
They basically copy values to variables which are global in odeiv, and 
pass their addresses to the C library functions of the thin binding. 
Example: Solve contains

status:= Gsl.gsl_odeiv2_driver_apply
	(solver.driver, solver.t1'Access, solver.t2,
	 solver.y(solver.y'First)'Access);

solver is a global record variable with components t1, t2 of type 
C.double, and solver.y of type

    type C_Array is array (Integer range <>) of aliased C.double;
    pragma Convention (C, C_Array);

The main program calls Init_Solve once, then Solve a hundred times, and 
finally Finit_Solve. It works and calculates the correct numbers. Now 
when I make odeiv generic:

generic
    dim:	Positive;
    type Float is digits<>;
package odeiv2 is
...

and substitute in the main program

    package Ode renames odeiv2;

with

    type Real is digits 6;
    package Ode is new odeiv2 (2, Real);

and change nothing else, I get a

raised STORAGE_ERROR : stack overflow or erroneous memory access
(SIGSEV, segmentation fault, when run under the debugger)
just at the line starting "status:= ..." shown above.
What would be an explication or a remedy for this behaviour?

-- 
Frank Hrebabetzky, Kronach	+49 / 9261 / 950 0565

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: generic provokes segmentation fault
  2020-05-17 14:19 generic provokes segmentation fault hreba
@ 2020-05-17 17:51 ` Dennis Lee Bieber
  2020-05-17 18:34 ` Dmitry A. Kazakov
  2020-05-17 21:02 ` Jeffrey R. Carter
  2 siblings, 0 replies; 9+ messages in thread
From: Dennis Lee Bieber @ 2020-05-17 17:51 UTC (permalink / raw)


On Sun, 17 May 2020 16:19:05 +0200, hreba <f_hreba@yahoo.com.br> declaimed
the following:


>
>generic
>    dim:	Positive;
>    type Float is digits<>;
>package odeiv2 is
>...
>
>and substitute in the main program
>
>    package Ode renames odeiv2;
>
>with
>
>    type Real is digits 6;
>    package Ode is new odeiv2 (2, Real);
>
>and change nothing else, I get a
>

	I'm not positive -- haven't really done enough Ada programming even
though I've liked the language since SIGPlan published the
reference/rationale based upon GREEN.

	However, if I interpret Barnes - Ada 2012, the parameters are setting

		dim <= 2

and defining

		type Float is digits Real

... and I'd be leery of that second statement...

	What happens if you instantiate using

		package Ode is new odev2 (2, 6)

OR change the template to

		type Float is private


-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
	wlfraed@ix.netcom.com    http://wlfraed.microdiversity.freeddns.org/

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: generic provokes segmentation fault
  2020-05-17 14:19 generic provokes segmentation fault hreba
  2020-05-17 17:51 ` Dennis Lee Bieber
@ 2020-05-17 18:34 ` Dmitry A. Kazakov
  2020-05-18 11:29   ` hreba
  2020-05-17 21:02 ` Jeffrey R. Carter
  2 siblings, 1 reply; 9+ messages in thread
From: Dmitry A. Kazakov @ 2020-05-17 18:34 UTC (permalink / raw)


On 2020-05-17 16:19, hreba wrote:

> I'll try to describe the problem without posting loads of code. Still 
> working on my thick binding of GSL/Odeiv2, the API of my package odeiv2 
> consists of 3 procedures:
>   - Init_Solve
>   - Solve
>   - Finit_solve
> They basically copy values to variables which are global in odeiv, and 
> pass their addresses to the C library functions of the thin binding. 

Well, that is certainly not good. IMO it is not Ada way to do this and 
it does not look like intended way of odeiv2 either. I looked shortly 
the interface of. It is decently designed and has operations to allocate 
a new structure and free it.

As a side note. It is not clear if the structure must be allocated in 
the C's memory pool. I would not experiment with that. Which could be 
reason for memory corruption on its own. That is frequently the case 
when the library has some bookkeeping attached to memory allocation.

But clearly the proper way to write an Ada binding to this would be a 
Limited_Controlled object. It would allocate the C object(s) in its 
Initialize using the official library call (or at some later point, e.g. 
on demand) and free them in the Finalize, again by the official means.

> generic
>     dim:    Positive;
>     type Float is digits<>;
> package odeiv2 is

I don't see any reason making it generic. The C library can only double. 
It does not make much sense to have a generic instance for Float, 
Long_Float, IEEE_Float_32 etc if the underlying computations are all double.

> raised STORAGE_ERROR : stack overflow or erroneous memory access
> (SIGSEV, segmentation fault, when run under the debugger)
> just at the line starting "status:= ..." shown above.
> What would be an explication or a remedy for this behaviour?

In the code you posted the parameter n in the call is missing. If that 
is not a typo error in your post, then you have got the stack mangled.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: generic provokes segmentation fault
  2020-05-17 14:19 generic provokes segmentation fault hreba
  2020-05-17 17:51 ` Dennis Lee Bieber
  2020-05-17 18:34 ` Dmitry A. Kazakov
@ 2020-05-17 21:02 ` Jeffrey R. Carter
  2020-05-18 20:21   ` hreba
  2 siblings, 1 reply; 9+ messages in thread
From: Jeffrey R. Carter @ 2020-05-17 21:02 UTC (permalink / raw)


On 5/17/20 4:19 PM, hreba wrote:
> 
> and substitute in the main program
> 
>     package Ode renames odeiv2;

Here the package is library-level.

> 
> with
> 
>     type Real is digits 6;
>     package Ode is new odeiv2 (2, Real);

Here it's local to your main-program procedure. Try making the instantiation 
library level and see if that works.

-- 
Jeff Carter
"Who wears beige to a bank robbery?"
Take the Money and Run
144

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: generic provokes segmentation fault
  2020-05-17 18:34 ` Dmitry A. Kazakov
@ 2020-05-18 11:29   ` hreba
  2020-05-18 12:36     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 9+ messages in thread
From: hreba @ 2020-05-18 11:29 UTC (permalink / raw)


On 2020-05-17 20:34, Dmitry A. Kazakov wrote:
> On 2020-05-17 16:19, hreba wrote:
> 
>> I'll try to describe the problem without posting loads of code. Still 
>> working on my thick binding of GSL/Odeiv2, the API of my package 
>> odeiv2 consists of 3 procedures:
>>   - Init_Solve
>>   - Solve
>>   - Finit_solve
>> They basically copy values to variables which are global in odeiv, and 
>> pass their addresses to the C library functions of the thin binding. 
> 
> Well, that is certainly not good. IMO it is not Ada way to do this and 
> it does not look like intended way of odeiv2 either. I looked shortly 
> the interface of. It is decently designed and has operations to allocate 
> a new structure and free it.

It is done in the intended way. Solve_Init allocates and Finit_Solve 
frees, calling the respective GSL/odeiv2 functions. My test program 
calls them in the correct sequence.

> As a side note. It is not clear if the structure must be allocated in 
> the C's memory pool. I would not experiment with that. Which could be 
> reason for memory corruption on its own. That is frequently the case 
> when the library has some bookkeeping attached to memory allocation.

In my program, I hold
  - references to structures allocated by the GSL C functions
  - data, which I have to provide, in variables of type C.double and
    arrays of them (with convention C).
Now what do you mean with experimenting in memory pools?

> But clearly the proper way to write an Ada binding to this would be a 
> Limited_Controlled object. It would allocate the C object(s) in its 
> Initialize using the official library call (or at some later point, e.g. 
> on demand) and free them in the Finalize, again by the official means.

My software is not yet in its final state. The strategy is to transform 
it step by step from the thin to the thick binding, including tests at 
each stage. Reason for that is ease of problem detection. The 
development might result in a controlled object in the end. Right now, 
my programs seems logically correct and a non-proper style certainly 
should not provoke an exception.

>> generic
>>     dim:    Positive;
>>     type Float is digits<>;
>> package odeiv2 is
> 
> I don't see any reason making it generic. The C library can only double. 
> It does not make much sense to have a generic instance for Float, 
> Long_Float, IEEE_Float_32 etc if the underlying computations are all 
> double.

That's correct with respect to the floating point type. What about dim? 
I need an array holding start and end values of the calculation. Without 
dim I would have to allocate it dynamically. I'm not writing 
safety-critical software, but shouldn't that be avoided if possible?

>> raised STORAGE_ERROR : stack overflow or erroneous memory access
>> (SIGSEV, segmentation fault, when run under the debugger)
>> just at the line starting "status:= ..." shown above.
>> What would be an explication or a remedy for this behaviour?
> 
> In the code you posted the parameter n in the call is missing. If that 
> is not a typo error in your post, then you have got the stack mangled.

What n are you talking about? The C prototype of the above function is

int gsl_odeiv2_driver_apply (gsl_odeiv2_driver * d, double *t,
                              const double t1, double y[]);

I you mean the dimension of the equation system, that is defined within 
Init_Solve.

Regards,
-- 
Frank Hrebabetzky, Kronach	+49 / 9261 / 950 0565

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: generic provokes segmentation fault
  2020-05-18 11:29   ` hreba
@ 2020-05-18 12:36     ` Dmitry A. Kazakov
  2020-05-18 20:16       ` hreba
  0 siblings, 1 reply; 9+ messages in thread
From: Dmitry A. Kazakov @ 2020-05-18 12:36 UTC (permalink / raw)


On 2020-05-18 13:29, hreba wrote:
> On 2020-05-17 20:34, Dmitry A. Kazakov wrote:
>> On 2020-05-17 16:19, hreba wrote:
>>
>>> I'll try to describe the problem without posting loads of code. Still 
>>> working on my thick binding of GSL/Odeiv2, the API of my package 
>>> odeiv2 consists of 3 procedures:
>>>   - Init_Solve
>>>   - Solve
>>>   - Finit_solve
>>> They basically copy values to variables which are global in odeiv, 
>>> and pass their addresses to the C library functions of the thin binding. 
>>
>> Well, that is certainly not good. IMO it is not Ada way to do this and 
>> it does not look like intended way of odeiv2 either. I looked shortly 
>> the interface of. It is decently designed and has operations to 
>> allocate a new structure and free it.
> 
> It is done in the intended way. Solve_Init allocates and Finit_Solve 
> frees, calling the respective GSL/odeiv2 functions. My test program 
> calls them in the correct sequence.

What is global variables you are talking about? gsl_odeiv2_driver seems 
to be allocated and initialized using library functions.

> That's correct with respect to the floating point type. What about dim? 
> I need an array holding start and end values of the calculation. Without 
> dim I would have to allocate it dynamically. I'm not writing 
> safety-critical software, but shouldn't that be avoided if possible?

You can always pass array as a parameter. The caller is responsible to 
allocate it in a way suitable for the caller, e.g. on the stack.

>>> raised STORAGE_ERROR : stack overflow or erroneous memory access
>>> (SIGSEV, segmentation fault, when run under the debugger)
>>> just at the line starting "status:= ..." shown above.
>>> What would be an explication or a remedy for this behaviour?
>>
>> In the code you posted the parameter n in the call is missing. If that 
>> is not a typo error in your post, then you have got the stack mangled.
> 
> What n are you talking about? The C prototype of the above function is
> 
> int gsl_odeiv2_driver_apply (gsl_odeiv2_driver * d, double *t,
>                               const double t1, double y[]);

I see, I thought it is another variant of apply.

> I you mean the dimension of the equation system, that is defined within 
> Init_Solve.

I do not know the library. To me it looks that dimension is a parameter 
to pass with other parameters when gsl_odeiv2_driver is allocated.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: generic provokes segmentation fault
  2020-05-18 12:36     ` Dmitry A. Kazakov
@ 2020-05-18 20:16       ` hreba
  2020-05-18 21:30         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 9+ messages in thread
From: hreba @ 2020-05-18 20:16 UTC (permalink / raw)


On 2020-05-18 14:36, Dmitry A. Kazakov wrote:

> What is global variables you are talking about? gsl_odeiv2_driver seems 
> to be allocated and initialized using library functions.

Initially, I tried the following:

  - the library defines a type with that driver as a private component
  - the client declares a variable of that type
  - the client calls the library's initialization function, which
    instanciates this variable (and the driver within)

I just was not able to get around that local/non-local object/pointer 
problem, and for now the driver is a global variable hidden in the 
library, initialized as a side effect of Init_Solve, as a workaround. 
This is unsatisfactory of course, because only 1 driver can be active at 
a time. Presently, I use flags to ensure initialization and to prevent 
multiple ones. In order not to mix topics, and to avoid posting lots of 
code here, I would like to come back on this later, with a minimal example.

Regards,
-- 
Frank Hrebabetzky, Kronach	+49 / 9261 / 950 0565

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: generic provokes segmentation fault
  2020-05-17 21:02 ` Jeffrey R. Carter
@ 2020-05-18 20:21   ` hreba
  0 siblings, 0 replies; 9+ messages in thread
From: hreba @ 2020-05-18 20:21 UTC (permalink / raw)


On 2020-05-17 23:02, Jeffrey R. Carter wrote:
> On 5/17/20 4:19 PM, hreba wrote:
>>
>> and substitute in the main program
>>
>>     package Ode renames odeiv2;
> 
> Here the package is library-level.
> 
>>
>> with
>>
>>     type Real is digits 6;
>>     package Ode is new odeiv2 (2, Real);
> 
> Here it's local to your main-program procedure. Try making the 
> instantiation library level and see if that works.
> 

I moved the package instantiation to an auxiliary package, created only 
for this reason, and it works!

Thanks,
-- 
Frank Hrebabetzky, Kronach	+49 / 9261 / 950 0565

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: generic provokes segmentation fault
  2020-05-18 20:16       ` hreba
@ 2020-05-18 21:30         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 9+ messages in thread
From: Dmitry A. Kazakov @ 2020-05-18 21:30 UTC (permalink / raw)


On 2020-05-18 22:16, hreba wrote:
> On 2020-05-18 14:36, Dmitry A. Kazakov wrote:
> 
>> What is global variables you are talking about? gsl_odeiv2_driver 
>> seems to be allocated and initialized using library functions.
> 
> Initially, I tried the following:
> 
>   - the library defines a type with that driver as a private component
>   - the client declares a variable of that type
>   - the client calls the library's initialization function, which
>     instanciates this variable (and the driver within)
> 
> I just was not able to get around that local/non-local object/pointer 
> problem, and for now the driver is a global variable hidden in the 
> library, initialized as a side effect of Init_Solve, as a workaround.

This what possibly crashes it because you don't not use official 
"constructors".

As I said it should be kind of

    type Driver is new Ada.Finalization.Limited_Controlled with private;
    procedure Apply (Object : in out Driver; ...);
    procedure Set (Object : in out Driver; ...); -- Set standard driver
    procedure Set (Object : in out Driver; ...); -- Set scaled driver
    ...
    overriding procedure Finalize (Object : in out Driver);
private
    type gsl_odeiv2_driver_struct is record ... end record;
    pragma Convention (C, gsl_odeiv2_driver_struct);
    type gsl_odeiv2_driver is access all gsl_odeiv2_driver_struct;
    pragma Convention (C, gsl_odeiv2_driver);

    type Driver is new Ada.Finalization.Limited_Controlled with record
       odeiv2 : gsl_odeiv2_driver;
    end record;

    procedure Set (Object : in out Driver; ...) is
    begin
       if Object.odeiv2 /= null then              -- Delete old, if any
          gsl_odeiv2_driver_free (Object.odeiv2); -- Could store and
          Object.odeiv2 := null;                  -- check its type
       end if;
       Object.odeiv2 := gsl_odeiv2_driver_alloc_standard_new (...);
    end Set ;

    procedure Finalize (Object : in out Driver) is
    begin
       if Object.odeiv2 /= null then
          gsl_odeiv2_driver_free (Object.odeiv2);
          Object.odeiv2 := null;
       end if;
    end Initialize;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-05-18 21:30 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-17 14:19 generic provokes segmentation fault hreba
2020-05-17 17:51 ` Dennis Lee Bieber
2020-05-17 18:34 ` Dmitry A. Kazakov
2020-05-18 11:29   ` hreba
2020-05-18 12:36     ` Dmitry A. Kazakov
2020-05-18 20:16       ` hreba
2020-05-18 21:30         ` Dmitry A. Kazakov
2020-05-17 21:02 ` Jeffrey R. Carter
2020-05-18 20:21   ` hreba

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox