David James wrote:
I converted my previous test from extended Pascal modules to units. This is unit dajunit3 and program daj3u, attached. This case works. daj3u makes the record using new().
So this bug is somehow module-specific. Peter is investigating it, but I don't know the current status...
However what I really want to do is to put this record into shared memory, so I moved to daj4u and dajunit4, attached. This fails.
Eventually, I tried setting the string's capacity before trying to assign a value to it, and, of course, then the program works.
My question is really what is the recommended way to do this: is it to set the string's capacity, or should I be calling some other function to initialise the record proerly after I shmat the shared memory? I assume that new(record_pointer) is initialising string capacities within the record, somehow.
Oh, I see. That's a completely new thing, something which hasn't been tried with GPC yet. So, let's see, what would be a good solution here...
- We could implement a routine that will initialize any data structure, just like `New' does. Technically, this might not be too difficult (Peter?), but OTOH, such a routine could be easily abused when applied to structures already initialized. (In the case of string or schema fields, this would not do much harm, but in the case of files, it could...)
- You could use some lower-level hooks into GPC's memory manager. These hooks already exist in the gpc unit (originally introduced to implement some BP compatible stuff in the system unit). They allow you to redirect any raw memory de-/allocations to user-defined routines, while GPC will still do all the initializations of strings, schemata, files, objects, etc.
I'm appending a crude example of this below. You might want to move the connect_shared_memory call into ShmGetMem, but it basically works.
If you ever Dispose of this record, you will have to provide a similar FreeMem routine, because otherwise the memory would be given to free() which might not know what to do with it (and might segfault or whatever)...
program daj4u(output);
uses gpc, dajunit4;
var size:integer; shmflg1:integer; shmflg2:integer; base_key:integer; shmid:integer; shmaddr:pointer; err:integer; OldGetMem : GetMemType;
function ShmGetMem (Size : SizeType) : Pointer; begin (* we probably should check Size here, but that's just a simple demo... *) ShmGetMem := shmaddr end;
begin
base_key:=16; size:=sizeof(ty_shared_data); shmflg1:=IPC_CREAT + 8#666; shmflg2:=0; writeln('Calling shmget with key ',base_key:1,' for size ',size:1, ' with flags ',shmflg1:1,' and ',shmflg2:1); connect_shared_memory(base_key,size,shmflg1,shmflg2,shmid,shmaddr,err); writeln('returned from connect_shared_memory for main shared memory ', shmid:1,' ',integer(shmaddr):1); if shmid=-1 then begin writeln('Failed to get main shared memory, reason ',err:1); halt; end;
if integer(shmaddr)=-1 then begin writeln('Failed to attach main shared memory, reason ',err:1); halt; end;
OldGetMem := GetMemPtr; GetMemPtr := @ShmGetMem; New (shared_data); GetMemPtr := OldGetMem;
with shared_data^ do begin sanity:=4567; writeln('sanity is ',sanity); prefix:='ABCD'; if (prefix='ABCD') then writeln('OK') else writeln('failed ',prefix,'|'); end; end.
Frank