Operating System - OpenVMS
1752782 Members
6190 Online
108789 Solutions
New Discussion юеВ

Re: /MODEL=ANSI & %CXX-W-MAYLOSEDATA in C++

 
SOLVED
Go to solution
River Tarnell
Advisor

/MODEL=ANSI & %CXX-W-MAYLOSEDATA in C++

I am trying to create an OpenVMS descriptor from an std::string in C++. This is the code I'm using:

#include
#include

int main() {
std::string text;
struct dsc$descriptor_s desc;
desc.dsc$b_class = DSC$K_CLASS_S;
desc.dsc$b_dtype = DSC$K_DTYPE_T;
desc.dsc$w_length = text.size();
desc.dsc$a_pointer = const_cast(text.data());
}

When compiled with no parameters, this works fine. But when I add /MODEL=ANSI, I get:

$ cxx/model=ansi test

desc.dsc$a_pointer = const_cast(text.data());
.............................^
%CXX-W-MAYLOSEDATA, cast from long pointer to short pointer will lose data.
at line number 10 in file DNFS1:[river]test.cxx;1

I was able to avoid the warning by forcing a short pointer size for the std::string::data() call, like this:

int main() {
struct dsc$descriptor_s desc;
std::string text;
#pragma pointer_size save
#pragma pointer_size short
desc.dsc$b_class = DSC$K_CLASS_S;
desc.dsc$b_dtype = DSC$K_DTYPE_T;
desc.dsc$w_length = text.size();
desc.dsc$a_pointer = const_cast(text.data());
#pragma pointer_size restore
}

However, I don't understand why this warning occurs, and why wrapping the data() call in #pragma pointer_size fixes it. What are the consequences of using the #pragma here?

(I did read the section on 64-bit pointers in the C++ users manual, but it didn't seem very clear on this...)

$ cxx/vers
HP C++ V7.3-009 for OpenVMS Alpha V8.3
7 REPLIES 7
John Gillings
Honored Contributor
Solution

Re: /MODEL=ANSI & %CXX-W-MAYLOSEDATA in C++

River,

From what you've written, it seems the compiler is behaving correctly. The data type std::string must be defined to allow the data field to live in 64 bit space, therefore the pointer text.data() is 64 bits. Your hand rolled descriptor is explicitly 32 bits. Therefore, copying the address from a 64 bits to 32 bits may drop the high order bits and your new pointer will point to the wrong place (but you knew that!).

I suspect using a pragma doesn't really fix the potential problem, it just hides it. In practice it probably doesn't matter, because the object "text" will probably be instantiated in P0 space, so the high order 32 bits of the 64 bit address will always be 0, so it won't matter that you're ignoring them.

To really fix the problem for all time, you need to use a data type that forces text to be in P0 space so the pointer will always conform to the 32 bit constraint you require. Alternatively, you could find or declare a different string type that uses 32 bit addresses.

If you know there's no chance for "text" to move out of P0 space, then the pragma is OK. On the other hand, if you just *hope* it won't end up out of P0 space, you'll have a bug that might be difficult to diagnose.

Without knowing the definition of "std::string" I can't say for sure, but one possibility is to move the declaration of "text" inside the "pointer_size short" window. That may change the properties of the object text. You can test it with:

int main() {
#pragma pointer_size save
#pragma pointer_size short
struct dsc$descriptor_s desc;
std::string text;
#pragma pointer_size restore

desc.dsc$b_class = DSC$K_CLASS_S;
desc.dsc$b_dtype = DSC$K_DTYPE_T;
desc.dsc$w_length = text.size();
desc.dsc$a_pointer = const_cast(text.data());

If you don't get the same warning on the assignment of the pointer, you know you've fixed it properly.
}
A crucible of informative mistakes
Hoff
Honored Contributor

Re: /MODEL=ANSI & %CXX-W-MAYLOSEDATA in C++

Or you head the other way...

#include
#include

int main() {
std::string text;
struct dsc$descriptor_s desc;
desc.dsc64$w_mbo = 1;
desc.dsc64$l_mbmo = ~0UL;
desc.dsc64$b_class = DSC$K_CLASS_S;
desc.dsc64$b_dtype = DSC$K_DTYPE_T;
desc.dsc64$q_length = text.size();
desc.dsc64$pq_pointer = const_cast(text.data());
}

Stephen Hoffman
HoffmanLabs LLC
Hoff
Honored Contributor

Re: /MODEL=ANSI & %CXX-W-MAYLOSEDATA in C++

Ignore last. grabbed wrong cut-and-paste.

#include
#include

int main() {
std::string text;
struct dsc64$descriptor_s desc;
desc.dsc64$w_mbo = 1;
desc.dsc64$l_mbmo = ~0UL;
desc.dsc64$b_class = DSC$K_CLASS_S;
desc.dsc64$b_dtype = DSC$K_DTYPE_T;
desc.dsc64$q_length = text.size();
desc.dsc64$pq_pointer = const_cast(text.data());
}

River Tarnell
Advisor

Re: /MODEL=ANSI & %CXX-W-MAYLOSEDATA in C++

Hi folks,

Thanks for the replies. I'm trying to fix the problem by using the 64-bit descriptor type in the code. This is the original code, which works correctly:

struct dsc$descriptor_s desc;
desc.dsc$b_class = DSC$K_CLASS_S;
desc.dsc$b_dtype = DSC$K_DTYPE_T;
desc.dsc$w_length = text.size();
desc.dsc$a_pointer = const_cast(text.data());
smg$put_line(&maindisplay, &desc, 0, 0, 0, 0, 0, 0);

This is the code using 64-bit descriptors:

struct dsc64$descriptor_s desc;
desc.dsc64$w_mbo = 1;
desc.dsc64$l_mbmo = ~0UL;
desc.dsc64$b_class = DSC$K_CLASS_S;
desc.dsc64$b_dtype = DSC$K_DTYPE_T;
desc.dsc64$q_length = text.size();
desc.dsc64$pq_pointer = const_cast(text.data());
smg$put_line(&maindisplay, &desc, 0, 0, 0, 0, 0, 0);

The 64-bit version gives an ACCVIO when run. (But strangely, it works if I pass the descriptor to lib$put_output; only smg$put_line is affected.)

What am I doing wrong here?
BGubenko
New Member

Re: /MODEL=ANSI & %CXX-W-MAYLOSEDATA in C++

River,

your original post was brought to my attention.

Let me add some information about C++ libraries on VMS: on OpenVMS
Alpha, in object model ANSI, the C++ Standard Library is a 64-bit
library. It means, among other things, that STL containers and
std::string allocate their elements in a 64-bit space. This behavior
is not affected by '#pragma pointer_size' or /pointer_size switch.

Your decision to use 64-bit descriptor is the correct one. You mention
in your last post that 64-bit descriptor works with lib$put_output() but
causes ACCVIO with smg$put_line(). I myself don't know the answer, but
I'd check if smg$ facility supports 64-bit descriptors. If it turns out
that, for some reason, you must use 32-bit descriptor, you should copy
sequence controlled by a 64-bit std::string to a 32-bit space (using
_strdup32(), for example), and initialize 32-bit descriptor with the
address of the copy.

Boris Gubenko
Maintainer of C++ libraries on Tru64 and VMS
Hoff
Honored Contributor

Re: /MODEL=ANSI & %CXX-W-MAYLOSEDATA in C++

Is SMG 64-bit? (AFAIK, it's not.) I'd tend to assume not here as this RTL is very old and fairly twisty.

I'd also guess that the error encountered here probably has a -1 address as part of the stackdump. This from the MBNO stuff in the descriptor; the 32-bit descriptor fields are deliberately built with 32-bit "illegal" values within a 64-bit descriptor, specifically to trigger these errors when the called code does not support 64-bit addressing.

Copy the value from 64-bit to 32-bit, in other words. There are various ways to do this, and some or all of the following routines can be of interest:

STR$COPY_DX
STR$GET1_DX
STR$GET1_DX_64
STR$ANALYZE_SDESC
STR$ANALYZE_SDESC_64
STR$COPY_R
STR$COPY_R_64
STR$FREE1_DX

The following text is from the STR manual:
--
"1.1.1 64-Bit Addressing Support (Alpha Only)

On Alpha systems, the String Manipulation (STR$) routines provide 64-bit virtual addressing capabilities as follows:

* All STR$ RTL routines now accept 64-bit addresses for arguments passed by reference.
* All STR$ RTL routines also accept either 32-bit or 64-bit descriptors for arguments passed by descriptor.
* In some cases a new routine was added to support a 64-bit addressing or data capability. These routines carry the same name as the original routine but with a _64 suffix. In general, both versions of the routine support 64-bit addressing but the routine with the _64 suffix also supports additional 64-bit capability. The 32-bit capabilities of the original routine are unchanged.

See the OpenVMS Programming Concepts Manual for more information about 64-bit virtual addressing capabilities."
--

There are similar statements in other spots, and if you haven't used 64-bit before, the Programming Concepts is a good starting point.

Also see Duane Smith's Digital Technical Journal article _Adding 64-bit Pointer Support to a 32-bit Run-time Library_, which is available at the following URL:
http://www.hpl.hp.com/hpjournal/dtj/vol8num2/vol8num2art7.pdf

Semi-related comments, since you're working on application code in this area...

For pedantic reasons, the DSC$K constants should be DSC64$K in the code I provided. The values associated with these symbolic constants are equal, however.

In general, I'd (also) be working to extricate SMG and the associated UI from within the mainline code of the application, and off into an application shareable image or such. Probably first to compartment the code, with planning for an eventual parallel user interface slotted in along side SMG in the application stack. This whether a data socket-based interface might be added, a traditional web-based UI, or any of other UI linkages or interfaces.
Hoff
Honored Contributor

Re: /MODEL=ANSI & %CXX-W-MAYLOSEDATA in C++

I'd not follow Boris's suggestion to use strdup and its C friends here, as that's not necessarily going to be sensitive to the different descriptors that can be in flight here. (Though if you do head this way, the LIB$ANALYZE_SDESC and its _64 cousin can be your friend.)

I view it as best to switch into "full OpenVMS RTL programming mode" here and would use the ("native"; non-C, non-C++) RTL descriptor interfaces once you start using string descriptors or SMG or other RTLs that use descriptors. The more that the C and C++ and descriptor mixing is intertwined in application code, the more likely that mistakes will creep in. Writing a new length or a new address into a dynamic descriptor, for instance, can lead to subtle run-time corruptions. Descriptors just aren't familiar to most C and C++ programmers.

Yes, strdup will work, but you'll have to contend with the various string and array descriptor structures yourself, and routines to deal with these descriptors already exist in the RTLs. (If you're working with SMG, you likely have your share of "weird" descriptors already in use, too.)

And FWIW, should it is a local concern, the more that descriptors are intertwined into the code, the less portable the code is, too.