Operating System - OpenVMS
1753389 Members
7211 Online
108792 Solutions
New Discussion юеВ

Re: CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

 
Steven Schweda
Honored Contributor

CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

I don't mean to nit-pick (not much, anyway),
but why am I (acting as an informal proxy for
the OpenSSL organization) getting these
annoying informational messages from what
should be identical situations? (Shouldn't
they be?)

alp $ type funcmixptr.c
#include

static void *(*realloc_func)(void *, size_t) = realloc;

static void (*free_func)(void *) = free;

int main( int argc, char **argv) {}

Case 1. No complaints:
alp $ cc /noobject /nopointer_size funcmixptr.c

Case 2. Annoying complaints:
alp $ cc /noobject /pointer_size = 32 funcmixptr.c

static void *(*realloc_func)(void *, size_t) = realloc;
..................................^
%CC-I-FUNCMIXPTR, In the initializer for realloc_func, function types differ bec
ause this declaration specifies "short pointer" and a previous declaration speci
fies "long pointer".
at line number 3 in file ALP$DKA0:[SMS.IZ]funcmixptr.c;4

static void (*free_func)(void *) = free;
..............................^
%CC-I-FUNCMIXPTR, In the initializer for free_func, function types differ becaus
e this declaration specifies "short pointer" and a previous declaration specifie
s "long pointer".
at line number 5 in file ALP$DKA0:[SMS.IZ]funcmixptr.c;4


The pointers are all supposed to be 32-bit in
both cases, aren't they? (Who writes these
header files?)

Who can explain why this is all my fault,
and/or why this is how it's supposed to work?
9 REPLIES 9
Steven Schweda
Honored Contributor

Re: CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

Oh, yeah...

alp $ cc /version
HP C V7.3-009 on OpenVMS Alpha V8.3

IT $ cc /version
HP C V7.3-019 on OpenVMS IA64 V8.3-1H1
Hoff
Honored Contributor

Re: CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

The following comment is based on looking at stdlib.h from this configuration:

HP C V7.1-015 on OpenVMS Alpha V8.3

This line:

void * realloc (__void_ptr64 __ptr, __size_t __size);

looks like it might be a bug, based on the other calls around it.

Switching the line over to this:

void * realloc (void *_ptr, __size_t __size);

fixes the first diagnostic. Here's the line and the replacement line in context:

void * calloc (__size_t __nmemb, __size_t __size);
void * malloc (__size_t __size);
// void * realloc (__void_ptr64 __ptr, __size_t __size);
void * realloc (void *_ptr, __size_t __size);
void * bsearch (const void *, const void *, __size_t, __size_t, int (*__comp
ar)(const void *, const void *));
void qsort (void *, __size_t, __size_t, int (*__compar)(const void *, co
nst void *));


This line:

void free (void *__nptr);

is always declared as a 64-bit function, irrespective of the requested pointer length; just as soon as you include /pointer_size on the command, this becomes a 64-bit pointer. This based on the preceding

# pragma __pointer_size 64

And that also too seems it might be a bug, too.

The C language gurus will probably need to have a look at this one.
Craig A Berry
Honored Contributor

Re: CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

$ help cc/pointer_size says


Specifying /POINTER_SIZE=32 directs the compiler to assume that all
pointers are 32-bit pointers. But unlike the default of
/NOPOINTER_SIZE, /POINTER_SIZE=32 enables use of the #pragma
pointer_size long and #pragma pointer_size short preprocessor
directives to control pointer size throughout your program.


and those pragmas are in use in stdlib.h. It looks as though giving a value to the /POINTER_SIZE qualifier enables the __INITIAL_POINTER_SIZE macro, but untangling the rest of what's going on in that header is more than I have time for at the moment. I'd be sure to compile with /list/show=(expansion,include) to see what prototypes and pragmas you're actually getting.
Steven Schweda
Honored Contributor

Re: CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

> The following comment [...]

Yup. That's how it looks around here, too.

> The C language gurus will probably need to
> have a look at this one.

I've sent a pointer off to
OpenVMS.Programs@hp, just in case it might
help.


> $ help cc/pointer_size says

I read it. Hence my complaint.

> [...] to see what prototypes and pragmas
> you're actually getting.

Not very interesting, actually. I'm getting
only what's in the system header files
(modules), so whatever happens is not my
fault (I claim). The complaints are only
"-I-", so the build procedure is unaffected,
and the stuff works, so they don't seem to
matter much, but I (for one) would be happier
if the system headers didn't give the
compiler indigestion on otherwise
harmless-looking code, depending on the
harmless-looking compiler options.
Lucifer Megacruel
Valued Contributor

Re: CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

Hi ,

I would point you Section 1.10 of the the OpenVMS CRTL manual where there is a good discussion of mixing and 32bit and 64 bit pointers in the same application . free is a function that accepts both 32bit and 64 bit pointers . In order to allocate 32 bit memory in 64 bit application you need to call _malloc32. So if you if you do

void *(*realloc_func)(void *, size_t) = _realloc32;

it will silence the compiler when compiled with /POINTER=32. There is nothing you can do to silence free , since it is designed to accept both 32 bit and 64 bit pointers. As a good programmer, I understand that it is annoying to find warnings when it is not your fault.

One caveat you need to be careful though:
The the 32 bit and 64 bit malloc calls corresponding lib$ routines in librtl. There is no communication between these 32 bit and 64 bit librtl routines. 32 bit routines allocate memory from P0 and 64 bit from P2 space. So if you allocate memory in 32bit space and use realloc64 to copy it will fail.
But in the program given below, if you remove the first line , you will find that librtl allocates the requested size. But this is because no malloc64 is not yet called, so it thinks it is a fresh allocation.

complile with /POINTER=LONG
#include
#include

int main()
{
char *test = malloc(1); /* remove this line to see the issue */
__char_ptr32 c1 = (__char_ptr32)_malloc32(1);
*c1 = 'x';
printf("%08llx : <%c>\n", c1, *c1);
char* c2 = (char*)realloc(c1, 10000); /* force reallocation */

if( c2 == NULL)
{
printf(" Realloc fails !" );
}
return EXIT_FAILURE;
}

--Lucifer
"To Denouce the Evils of Truth and Love. To cause may hem and destruction and necromancy , Lucifer is here"
Steven Schweda
Honored Contributor

Re: CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

> I would point you Section 1.10 of the the
> OpenVMS CRTL manual

I've been there, thanks.

> where there is a good
> discussion of mixing and 32bit and 64 bit
> pointers in the same application . [...]

Which, as you can see, _I_ wasn't doing.

> [...] So if you if you do [...]

My complaint wasn't that it was impossible to
avoid the compiler complaints. My complaint
was that explicitly specifying the default
pointer size gives results which differ from
those one gets from implicitly accepting the
default pointer size. This seems to me to be
undesirable.

I've already had to add enough functional
work-arounds to this code to get past the
argv[] problems:

http://h30499.www3.hp.com/t5/Languages-and-Scripting/CC-POINTER-SIZE-64-ARGV-Alpha-NULL-termination-of-argv/m-p/4762475#M8190


I hate to (try to) add more additional
VMS-specific clutter to a widely portable
open-source project than is absolutely
necessary.

Hoff
Honored Contributor

Re: CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

On thinking about it and irrespective of whether the call accepts 32- or 64-bit, having free always be declared with 64-bit pointers is broken. It's valid in terms of the implicit promotion, but fails in terms of the compiler diagnostics.

The other standard library calls in that same wad as the free call are equally likely to toss a spurious diagnostic, if (for whatever reason) you want or need to pass those around as pointers, too.

Your options are exceedingly limited, at least for now. Probably the best available of a bad lot is suppressing the compiler diagnostic via #pragma, possibly introduced via the usual /FIRST_INCLUDE mechanism.

This for either for production builds, or for all builds.

Less desirably, replace the free with your own jacket with a correct declaration, or with a cast in the assignment.

Even less desirably, pull the header file and diff/patch it. Fix it.

The first include diagnostic suppression approach will will reduce the visibility of changes to the OpenSSL folks; they'll end up with a VMS-specific compile command and a VMS-specific (first include) header file, which probably won't concern them quite as much as scattering VMS changes in the bulk of the OpenSSL codebase.

Comment the details of the #pragma for the suppression, obviously.
JagadishM
Occasional Advisor

Re: CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

Hello,
Below is the suggestion for the customer:
-----------------------------------------------------------
$ type my_header.h
#include

#if __INITIAL_POINTER_SIZE == 32
void *(*realloc_func)(void *, size_t) = _realloc32;
#elif __INITIAL_POINTER_SIZE == 64
void *(*realloc_func)(void *, size_t) = _realloc64;
#else
void *(*realloc_func)(void *, size_t) = realloc;
#endif

#if __INITIAL_POINTER_SIZE == 32 || !defined __INITIAL_POINTER_SIZE
# pragma __pointer_size __save
# pragma __pointer_size 64
#endif
void (*free_func)(void *) = free;

#if __INITIAL_POINTER_SIZE == 32 || !defined __INITIAL_POINTER_SIZE
# pragma __pointer_size __restore
#endif

$
$ type FUNCMIXPTR_MY_HEADER.C;
#include "my_header.h"
int main( int argc, char **argv) {}

$

$ cc /noobject /pointer_size=64 FUNCMIXPTR_MY_HEADER
$ cc /noobject /pointer_size=32 FUNCMIXPTR_MY_HEADER
$ cc /noobject /nopointer_size FUNCMIXPTR_MY_HEADER
$
-----------------------------------------------------------

Thank you,
OpenVMS CRTL Engineering
WW304289
Frequent Advisor

Re: CC /POINTER_SIZE = 32 v. <stdlib.h> -- %CC-I-FUNCMIXPTR

As others have pointed out, the realloc() and free() functions are declared in as expecting a 64-bit pointer. This technique is used throughout the C Run-Time Library headers for all functions accepting a 64-bit pointer.

Such function prototypes allow passing a 64-bit pointer even in a program compiled with /pointer_size=32. It is done to support mixed pointer size mode, which is something that, to the best of my knowledge, no other platform supports, except, may be, Tru64 UNIX, but I don't remember all the details.

The best workaround is, probably, using "convenient" types from . This header is included by all other C RTL headers.

#include
static void *(*realloc_func)(__void_ptr64, size_t) = realloc;
static void (*free_func)(__void_ptr64) = free;

As for portability, one needs to define what portability means in this case as the original program compiles cleanly in strict ANSI mode. It is when the program is compiled with VMS-specific /pointer_size switch, the compiler starts emitting diagnostics.

-Boris