Hello, Maybe that is a trivial question but I want to know whether there is a way to turn on/off range checking with GPC. I missed to find it in the man pages, seems it is in the set of options inherited from GCC which I'm not very familiar with ;-) Thanks in advance, Adam Naumowicz
-------------------------------------- WWW: http://math.uwb.edu.pl/~adamn/ --------------------------------------
Hello.
I am sorry for somewhat lengthy email, I tried to get most of the details here. I could not find detailed discussion of this topic in documentation, so this is a short investigation.
First some description: I need to implement access to some data stored in special binary format for reading which large chunks of C code exist. On the other hand it would be easier/cleaner to do data processing in pascal (It is really nice to use schemata for some purposes). So I thought to create some c functionds which would access data and pass it to pascal program. It would be nice to have c functions allocate and fill buffers and then have pascal code dispose them after processing. So I tried to test what happens. Below is the model code which is supposed to represent such situation. In fact it tests passage of buffers in both ways: I allocate small array on pascal side, pass it to c, then reallocate it there (slightly larger block) - actually I use free and then malloc, but realloc gave the same result. Then upon return to pascal I dispose the buffer. To tell the truth I did not expect things to work at all, but it appears that they do work - one way only. Unfortunately the opposite way to what I need. So here goes the code: (I have gpc 20010623, based on 2.95.3 20010315 (release), gcc 2.95.3, glibc 2.2.2, kernel 2.4.4) ---------- Pascal program ----------
program testFuncInvocation;
type Tst=array[0..9]of char;Pst=^Tst; var x:Pst;
{$L c.c} function cfunc(var x:pointer):integer;asmname 'cFunc'; {$L cmem.c} procedure cFree(p:pointer);C;
begin writeln('pascal program started'); x:=new(Pst);x^:='0123456789';writeln('x=',x^,', @x=',cardinal(x)); writeln('calling c function...'); cfunc(x); writeln('back in pascal; new @x=',cardinal(x),', x=',x^); cFree(x); end.
------------- c file: c.c ------------ #include <stdio.h> #include <stdlib.h>
int cFunc(char** x){ printf("\ncFunc called; x=%s\n",*x); free(*x); *x=(char*)malloc(15); *x="0123456789abcde"; printf("realloced x, new @x=%d, x=%s\n",(int)*x,*x); fflush(stdout); }
------------ output of this program: ------------ pascal program started x=0123456789, @x=134716664 calling c function...
cFunc called; x=0123456789 realloced x, new @x=134659990, x=0123456789abcde back in pascal; new @x=134659990, x=0123456789 Segmentation fault
--------------------- end of code section ---------------------
So, as can be seen, c has no problem disposing the buffer allocated on pascal side. Pascal gets back correct address, but then fails to deallocate passed buffer. I originally tried dispose(x) in pascal code to deallocate x, with the same result. So then I thought that might be dispose is not just calling glibc's free() but is relying on internal tracking of variables. But calling free directly does not help here. So what would be the correct way to pass disposable buffers from c to pas, preferrably without having to specify the size (I mean here the way dispose and free() work. I understand that I will need to keep track of how many data I got there)? Well if this will be the only catch I don't mind at all, it's just easier to make a mistake this way.
George
Sorry for the late reply ...
George Shapovalov wrote:
I am sorry for somewhat lengthy email, I tried to get most of the details here. I could not find detailed discussion of this topic in documentation, so this is a short investigation.
First some description: I need to implement access to some data stored in special binary format for reading which large chunks of C code exist. On the other hand it would be easier/cleaner to do data processing in pascal (It is really nice to use schemata for some purposes). So I thought to create some c functionds which would access data and pass it to pascal program. It would be nice to have c functions allocate and fill buffers and then have pascal code dispose them after processing. So I tried to test what happens. Below is the model code which is supposed to represent such situation. In fact it tests passage of buffers in both ways: I allocate small array on pascal side, pass it to c, then reallocate it there (slightly larger block) - actually I use free and then malloc, but realloc gave the same result. Then upon return to pascal I dispose the buffer. To tell the truth I did not expect things to work at all, but it appears that they do work - one way only. Unfortunately the opposite way to what I need.
In general, you can indeed expect it to work both ways.
There's only one catch: If the program ever uses Mark/Release (or something which uses them itself such as the HeapMon unit), you cannot free pointers in C that were allocated in Pascal. But since you don't use Mark/Release, that's not relevant here.
Unfortunately, your example contains a fe problems:
- cmem.c is missing. I added for it: #include <stdlib.h> void cfree (void *p) { free (p); }
- cFunc does not return a value, and the Pascal code treats the function as a procedure.
- The pointer in Pascal is declared as fixed-size, so even after the reallocation, Pascal treats its size as 10 chars and writes it accordingly.
- The C statemtent `*x="0123456789abcde"' assigns a *pointer* rather than copying an array. So you try, in the end, to free a C string constant which obviously may crash (regardless whether you do that in Pascal or C).
So, the problem here is a misunderstanding of C's pointer/array semantics (and therefore a little OT ;-). I don't know if that's the problem you had in your real code, but if there's something else for which GPC may be to blame, let us know.
Frank