Interesting!  Is this (1 and 2) actually addressed anywhere official that 
discusses PL/I and C ILC?  One would hope so...  I imagine that PL/I could 
simply call the C free() function itself, in any case.

I'm not looking to make anything in particular work in PL/I, but rather 
thinking about how the new "dynamic-length elementary items" supported by the 
latest COBOL standard (2014) could work when interfacing with C strings (and 
PL/I variable length strings, for that matter).  I thought it would be useful 
to know what PL/I does in this regard.

Frank
________________________________
From: IBM Mainframe Discussion List <IBM-MAIN@LISTSERV.UA.EDU> on behalf of 
Bernd Oppolzer <bernd.oppol...@t-online.de>
Sent: Wednesday, June 21, 2017 2:04 PM
To: IBM-MAIN@LISTSERV.UA.EDU
Subject: Re: PL/I and C (was Re: Simple (?) C question)

Hi Frank,

1.) yes, the C area acquired by malloc must be freed by someone

2.) unfortunately, the PL/1 FREE statement cannot do it, because,
as I recently observed while checking some PL/1 modules for storage leaks,
PL/1 stores its heap areas (allocated by PL/1 ALLOC / FREE) in the LE
ANYWHERE HEAP,
but C - with malloc - uses one of the (in theory many) LE USER HEAPs,
so PL/1 FREE will not be able to FREE the C malloc areas. At least, that's
what I think. You will IMO have to provide a C function that frees the
area on behalf of the PL/1 caller (using C free). At least, I believe
that's
what you should do.

3.) at one of my former customer's site, we decided to write our own
storage management, callable from all languages. Of course, it is based
on normal GETMAIN / FREEMAIN. If you do this carefully, you will even
be able to outperform the LE storage management (to some small percent
values). With this solution, you don't have such problems as outlined
above.

4.) for my private Stanford Pascal compiler project (the compiler runs
on MVS and CMS on Hercules, but even on today's z/OS), I rewrote the
LE storage management in Pascal, from some descriptions and presentations
available from IBM. This took me some weeks last year, but it works without
problems. Look here: http://bernd-oppolzer.de/job9.htm
Oppolzer - Informatik / Stanford Pascal 
Compiler<http://bernd-oppolzer.de/job9.htm>
bernd-oppolzer.de
Updated version of the Stanford Pascal Compiler designed to run on VM/370 Rel. 
6 under the Hercules emulator. It should also run on today's z/VM and some, or 
all ...



5.) I also wrote some diagnose routines (for LE on z/OS) that check for
storage leaks
on the fly (while the programs run).

Please call me offline, if you want to know more.

Kind regards

Bernd


Am 21.06.2017 um 21:01 schrieb Frank Swarbrick:
> I know we have some PL/I experts here, and I can't seem to subscribe to the 
> PL/I listserv, so I'll ask here.  I am not a PL/I programmer, but I've 
> studied it to some degree.  I believe the following is a valid PL/I program 
> that would invoke the C language get_static_string() function (as well as one 
> called get_dynamic_string() that does a malloc() and returns it's result).
>
> pli_calling_C:
>    procedure
>
>    dcl s_str    ext('get_static_string')
>                 entry( entry returns( byvalue pointer ) )
>                 options( byvalue nodescriptor );
>    dcl d_str    ext('get_dynamic_string')
>                 entry( entry returns( byvalue pointer ) )
>                 options( byvalue nodescriptor );
>    dcl str1     char(*) varz based(str1ptr), str1ptr pointer;
>    dcl str2     char(*) varz based(str2ptr), str2ptr pointer;
>
>    str1ptr = s_str();
>    display(str1);
>    str2ptr = d_str();
>    display(str2);
> end;
>
> My question is, can/must the PL/I program do free(str2ptr) in order to 
> release the storage for the dynamically allocated string?  (And obviously NOT 
> do this for str1ptr.)
>
> Side request... Could someone post the PL/I "JNI" copybook?
>
> Thanks, Frank
>
> ________________________________
> From: Frank Swarbrick
> Sent: Tuesday, June 20, 2017 9:47 AM
> To: IBM Mainframe Discussion List
> Subject: Re: Simple (?) C question
>
>
> Thanks John.  I know of no code that does this, nor do I intend to implement 
> any.  What I was really trying to determine is if a routine could possibly 
> (rightly or wrongly) return a pointer to a field that was statically 
> allocated rather than dynamically allocated.  Which would mean that the 
> caller should not, for example, attempt a free() on that pointer.  I've been 
> pondering the COBOL 2014 standard and how it might interact with C in this 
> regard.
>
> Thanks to everyone who answered.
>
> Frank
>
> ________________________________
> From: IBM Mainframe Discussion List <IBM-MAIN@LISTSERV.UA.EDU> on behalf of 
> John McKown <john.archie.mck...@gmail.com>
> Sent: Monday, June 19, 2017 7:59 PM
> To: IBM-MAIN@LISTSERV.UA.EDU
> Subject: Re: Simple (?) C question
>
> On Mon, Jun 19, 2017 at 4:25 PM, Frank Swarbrick <
> frank.swarbr...@outlook.com> wrote:
>
>> I know there are at least a few C developers here, so I was wondering if
>> you could answer a question.  Is the following valid C?  (I'm not asking if
>> one should actually do it; only if its valid at all.)
>> char *get_static_string(void) {
>>      static char str[81] = "This is a statically allocated C string";
>>      return str;
>> }
>>
>>
>> printf("%s", get_static_string());
>>
>>
>> I don't have a C compiler available at work else I'd try it myself.
>>
>> Frank
>>
>>
> You have gotten some good answers. So I will just interject a bit of,
> perhaps off center, comment. Your code, as written compiles just fine. But
> it is basically very dangerous. The reason is that you are returning a
> pointer which could be used to overwrite storage. This is also known as "a
> bad thing" and is basically an attack vector by malicious code. I don't
> know the actual intent of your question. But I would suggest using the
> #pragma string(readonly) in your example. E.g. compile "get_static_string"
> in its own compilation unit (i.e. by itself)
>
> #pragma strings(readonly)
> const char *get_static_string() {
>      const static char[] = "This is a statically allocated C string"; // let
> the compiler figure out the length;
>      return str;
> }
>
>
> I can hear you saying: "But, really, I need up be able to update this
> string on occasion." If so, then I would greatly suggest that you create a
> "compilation unit" (single file containing source which is compiled
> independently ) such as:
>
> #
> file static_string.c
>
> #if ! defined(MAXSTRLEN)
> #define MAXSTRLEN 100
> #endif
> #include <string.h>
>
> static char str[MAXSTRLEN];
>
> const char *get_static_string(void) {
>         return str;
> }
>
> int set_static_string(char *set_to_value) {
>         int len_to_set = strnlen(set_to_value,MAXSTRLEN);
>         if (len_to_set >= MAXSTRLEN)  // string too long!
>                 return 1; // tell caller NO GO!
>         memcpy(str,set_to_value,len_to_set); // fast copy
>         return 0;
> }
>
> Since the variable "str" is defined as "static" and outside of any
> function definition, it is "global" to the "compilation unit", but is not
> known outside of it (i.e. it is not an external name). You compile the
> above to "object" code. You may be able to bind it into a LOADLIB, but I
> think you'll get some "external reference not found" type messages for
> "main".
>
> Anyway, the above could be similar to:
>
> # file use_static_string.c
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <stdint.h>
> const char *get_static_string(void);
> int set_static_string(char *);
> int main(int argc, char *argv[]){
>         char set_to_1[]="Set to this value";
>         char set_to_2[]="Set to another value";
>         const char *return_static_string;
>         int retRC;
>         retRC=set_static_string(set_to_1);
>         if (retRC != 0) {
>                 printf("retRC=%d\n",retRC);
>                 exit(1);
>         }
>         return_static_string=get_static_string();
>         printf("%s\n",return_static_string);
>         retRC=set_static_string(set_to_2);
>         if (retRC != 0) {
>                 printf("retRC=%d\n",retRC);
>                 exit(1);
>         }
>         return_static_string=get_static_string();
>         printf("%s\n",return_static_string);
> }
>
> Please note that I did test the above, but not on z/OS. I did it on
> Linux/Intel at home. But it is fairly generic and so should work on z/OS
> with xlc as well.
>
> Also note the use of MAXSTRLEN. This is really a "preprocessor" value. Why
> did I use it as I did? Because if 100 is not correct, you can change the
> MAXSTRLEN value on the compile with the -D compile option. I don't
> remember how to do this with JCL, but on a UNIX shell prompt, you can do
> something like:
>
> xlc -c -DMAXSTRLEN=256 -o static_string.o static_string.c # MAX string
> length is 256 (255 chars + NUL ending) # compile, don't link
> xlc -o use_static_string use_static_string.c static_string.o # compile and
> link object from above
>
>
>
> --
> Veni, Vidi, VISA: I came, I saw, I did a little shopping.
>
> Maranatha! <><
> John McKown
>
> ----------------------------------------------------------------------
> For IBM-MAIN subscribe / signoff / archive access instructions,
> send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN
>
> ----------------------------------------------------------------------
> For IBM-MAIN subscribe / signoff / archive access instructions,
> send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN

Reply via email to