Dear Experts,
I need a function that takes a float, swaps its endianness (htonl) in
place, and returns a char* pointer to its first byte. This is one of a
family of functions that prepare different data types for passing to
another process.
I have got confused by the rules about what won't work, what will work,
and what might work, when casting. Specifically, I have an
implementation that works until I remove my debugging, at which point
the compiler seems to decide that it can optimise away the writes to the
bytes other than the first, or something like that. Here it is:
template <typename T>
inline const char* encode_arg(T& t); // linker error if you try to
// encode a type for which there
// is no implementation
// This one works:
template <>
inline const char* encode_pq_arg<i nt>(int& i) {
i = htonl(i);
return reinterpret_cas t<const char*>(&i);
}
// This one doesn't:
template <>
inline const char* encode_arg<floa t>(float& f) {
uint32_t* ptr = reinterpret_cas t<uint32_t*>(&f );
*ptr = htonl(*ptr);
const char* cptr = reinterpret_cas t<const char*>(ptr);
return cptr;
}
When I dump cptr[0] to cptr[3] before the return, it works. Without the
debug, it fails; it's obviously hard to see what ends up in the result
in that case, but it looks undefined.
So, is there some tweak that will make this work, and be certain to
work? Am I better off using a union, or is that even less defined?
Does anyone know what the rules actually are?
Many thanks,
Phil. 12 2135
Phil Endecott wrote:
Dear Experts,
I need a function that takes a float, swaps its endianness (htonl) in
place, and returns a char* pointer to its first byte. This is one of a
family of functions that prepare different data types for passing to
another process.
I have got confused by the rules about what won't work, what will work,
and what might work, when casting. Specifically, I have an
implementation that works until I remove my debugging, at which point
the compiler seems to decide that it can optimise away the writes to the
bytes other than the first, or something like that. Here it is:
template <typename T>
inline const char* encode_arg(T& t); // linker error if you try to
// encode a type for which there
// is no implementation
// This one works:
template <>
inline const char* encode_pq_arg<i nt>(int& i) {
Typo? ^^
i = htonl(i);
return reinterpret_cas t<const char*>(&i);
}
Did you intend the bytes of the passed value to be swapped?
// This one doesn't:
template <>
inline const char* encode_arg<floa t>(float& f) {
uint32_t* ptr = reinterpret_cas t<uint32_t*>(&f );
*ptr = htonl(*ptr);
const char* cptr = reinterpret_cas t<const char*>(ptr);
return cptr;
}
When I dump cptr[0] to cptr[3] before the return, it works. Without the
debug, it fails; it's obviously hard to see what ends up in the result
in that case, but it looks undefined.
What doesn't work?
--
Ian Collins.
Ian Collins wrote:
Phil Endecott wrote:
>Dear Experts,
I need a function that takes a float, swaps its endianness (htonl) in place, and returns a char* pointer to its first byte. This is one of a family of functions that prepare different data types for passing to another process.
I have got confused by the rules about what won't work, what will work, and what might work, when casting. Specifically, I have an implementati on that works until I remove my debugging, at which point the compiler seems to decide that it can optimise away the writes to the bytes other than the first, or something like that. Here it is:
template <typename T> inline const char* encode_arg(T& t); // linker error if you try to // encode a type for which there // is no implementation
// This one works: template <> inline const char* encode_pq_arg<i nt>(int& i) {
Typo? ^^
Yes, copy&pastism, sorry!
> i = htonl(i); return reinterpret_cas t<const char*>(&i); }
Did you intend the bytes of the passed value to be swapped?
Yes; the caller doesn't need the value any more, so I swap it in-place
rather than making a copy. If I made a copy then I would have to
allocate memory for it and free it later.
>// This one doesn't: template <> inline const char* encode_arg<floa t>(float& f) { uint32_t* ptr = reinterpret_cas t<uint32_t*>(&f ); *ptr = htonl(*ptr); const char* cptr = reinterpret_cas t<const char*>(ptr); return cptr; }
When I dump cptr[0] to cptr[3] before the return, it works. Without the debug, it fails; it's obviously hard to see what ends up in the result in that case, but it looks undefined.
What doesn't work?
The four bytes pointed to by the const char* that this function returns
eventually get sent to a socket, and I can observe them at the other
end. They are wrong, i.e. if I pass 2.0 then the value at the other end
might be 8.923461290e-44. There is some non-determinism in the values I
see, which makes me think that I'm looking at uninitialised memory
rather than a systematic corruption. My first thought was to add
somethng like this:
std::cout << "cptr[0] = " << static_cast<int >(cptr[0]) << ....etc for
[1] to [3] ... << "\n";
However, as soon as I add this (just before the return statement), it
works: the correct value is seen in the other process. My feeling is
that the cptr[n] expressions in the debugging tell the compiler that
these bytes are needed; when the debuging is not there, it thinks that
they are not used, and optimises them away. Can you think of any other
explanation?
Regards,
Phil.
Phil Endecott wrote:
[..]
The four bytes pointed to by the const char* that this function
returns eventually get sent to a socket, and I can observe them at
the other end. They are wrong, i.e. if I pass 2.0 then the value at
the other end might be 8.923461290e-44. There is some
non-determinism in the values I see, which makes me think that I'm
looking at uninitialised memory rather than a systematic corruption. My
first thought was to add somethng like this:
std::cout << "cptr[0] = " << static_cast<int >(cptr[0]) << ....etc for
[1] to [3] ... << "\n";
However, as soon as I add this (just before the return statement), it
works: the correct value is seen in the other process. My feeling is
that the cptr[n] expressions in the debugging tell the compiler that
these bytes are needed; when the debuging is not there, it thinks that
they are not used, and optimises them away. Can you think of any
other explanation?
Compilers are written by humans. Errare humanum est. Hence all
compilers have bugs, known and unknown. If you want to know whether
the bug you're encountering is known, contact the compiler writers.
If you just want a work-around, disable optimization for the small
module in which this function (these functions) is (are), and see if
it makes any difference. I've seen a significant improvement from
seemingly random behaviour with the HP and Sun compilers before, and
even <gasp!with Microsoft's VC++ compiler, if optimizations are
disabled locally.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
On Sep 15, 5:26 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
Phil Endecott wrote:
[..]
The four bytes pointed to by the const char* that this function
returns eventually get sent to a socket, and I can observe them at
the other end. They are wrong, i.e. if I pass 2.0 then the value at
the other end might be 8.923461290e-44. There is some
non-determinism in the values I see, which makes me think that I'm
looking at uninitialised memory rather than a systematic corruption. My
first thought was to add somethng like this:
std::cout << "cptr[0] = " << static_cast<int >(cptr[0]) << ....etc for
[1] to [3] ... << "\n";
However, as soon as I add this (just before the return statement), it
works: the correct value is seen in the other process. My feeling is
that the cptr[n] expressions in the debugging tell the compiler that
these bytes are needed; when the debuging is not there, it thinks that
they are not used, and optimises them away. Can you think of any
other explanation?
Compilers are written by humans. Errare humanum est. Hence all
compilers have bugs, known and unknown. If you want to know whether
the bug you're encountering is known, contact the compiler writers.
If you just want a work-around, disable optimization for the small
module in which this function (these functions) is (are), and see if
it makes any difference. I've seen a significant improvement from
seemingly random behaviour with the HP and Sun compilers before, and
even <gasp!with Microsoft's VC++ compiler, if optimizations are
disabled locally.
It looks like an auto optimization error.Maybe - as a result of
pointer algebra on small argument type - the enregisterd parameter is
copied to stack and operated upon ,and filled with rubish at
return(you are returning a pointer to the automatic variable).
can you write this:
union exg
{
float f;
char cl[sizeof(float)];
exg& IndianSwap();
};
exg e={value};
e.IndianSwap();
and leave the optimization to the compiler(I think modern compilers
can do fine on this special case)?
regards,
FM.
terminator wrote:
[..]
can you write this:
union exg
{
float f;
char cl[sizeof(float)];
exg& IndianSwap();
};
exg e={value};
e.IndianSwap();
and leave the optimization to the compiler(I think modern compilers
can do fine on this special case)?
Initialising (or assigning to) one part of a union and using another
has undefined behaviour. Or at least it used to. So, I'd stay away
from such code, it is definitely non-portable, although probably just
as reinterpret_cas t to an array of chars.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
On Sep 15, 7:46 pm, terminator <farid.mehr...@ gmail.comwrote:
On Sep 15, 5:26 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
Phil Endecott wrote:
[..]
The four bytes pointed to by the const char* that this function
returns eventually get sent to a socket, and I can observe them at
the other end. They are wrong, i.e. if I pass 2.0 then the value at
the other end might be 8.923461290e-44. There is some
non-determinism in the values I see, which makes me think that I'm
looking at uninitialised memory rather than a systematic corruption. My
first thought was to add somethng like this:
std::cout << "cptr[0] = " << static_cast<int >(cptr[0]) << ....etc for
[1] to [3] ... << "\n";
However, as soon as I add this (just before the return statement), it
works: the correct value is seen in the other process. My feeling is
that the cptr[n] expressions in the debugging tell the compiler that
these bytes are needed; when the debuging is not there, it thinks that
they are not used, and optimises them away. Can you think of any
other explanation?
Compilers are written by humans. Errare humanum est. Hence all
compilers have bugs, known and unknown. If you want to know whether
the bug you're encountering is known, contact the compiler writers.
If you just want a work-around, disable optimization for the small
module in which this function (these functions) is (are), and see if
it makes any difference. I've seen a significant improvement from
seemingly random behaviour with the HP and Sun compilers before, and
even <gasp!with Microsoft's VC++ compiler, if optimizations are
disabled locally.
It looks like an auto optimization error.Maybe - as a result of
pointer algebra on small argument type - the enregisterd parameter is
copied to stack and operated upon ,and filled with rubish at
return(you are returning a pointer to the automatic variable).
It's not a bug. The compiler is allowed to assume that a
variable is only modified/read through expressions of its type,
or through expressions of char or unsigned char type. The fact
that something is modified through an uint32_t* is irrelevant
when the compiler is optimizing accesses to a float, for
example.
can you write this:
union exg
{
float f;
char cl[sizeof(float)];
exg& IndianSwap();
};
exg e={value};
e.IndianSwap();
and leave the optimization to the compiler(I think modern
compilers can do fine on this special case)?
If "IndianSwap " accesses cl, then it's undefined behavior.
--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
On Sep 15, 8:23 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
terminator wrote:
[..]
can you write this:
union exg
{
float f;
char cl[sizeof(float)];
exg& IndianSwap();
};
exg e={value};
e.IndianSwap();
and leave the optimization to the compiler(I think modern compilers
can do fine on this special case)?
Initialising (or assigning to) one part of a union and using another
has undefined behaviour. Or at least it used to.
It still does, although some compilers may guarantee this as an
extension. (I think g++ does.)
So, I'd stay away
from such code, it is definitely non-portable, although probably just
as reinterpret_cas t to an array of chars.
reinterpret_cas t to an array of char's is probably OK. The
problem in the original code was assigning through the
uint32_t*; that's undefined behavior if, as was the case, the
pointer was the result of a reinterpret_cas t from a float*.
--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
On Sep 14, 12:02 pm, Phil Endecott
<spam_from_usen et_0...@chezphi l.orgwrote:
Dear Experts,
I need a function that takes a float, swaps its endianness (htonl) in
place, and returns a char* pointer to its first byte. This is one of a
family of functions that prepare different data types for passing to
another process.
I have got confused by the rules about what won't work, what will work,
and what might work, when casting. Specifically, I have an
implementation that works until I remove my debugging, at which point
the compiler seems to decide that it can optimise away the writes to the
bytes other than the first, or something like that. Here it is:
template <typename T>
inline const char* encode_arg(T& t); // linker error if you try to
// encode a type for which there
// is no implementation
// This one works:
template <>
inline const char* encode_pq_arg<i nt>(int& i) {
i = htonl(i);
return reinterpret_cas t<const char*>(&i);
}
// This one doesn't:
template <>
inline const char* encode_arg<floa t>(float& f) {
uint32_t* ptr = reinterpret_cas t<uint32_t*>(&f );
*ptr = htonl(*ptr);
const char* cptr = reinterpret_cas t<const char*>(ptr);
return cptr;
}
And it shouldn't. The encode_arg() function is effectively returning a
pointer to a local variable (the parameter f). So the caller of
encode_arg() receives a pointer to an object that no longer exists;
and therefore the value of the bytes obtained by dereferencing the
returned pointer - could be anything.
Greg
Greg Herlihy wrote:
On Sep 14, 12:02 pm, Phil Endecott
<spam_from_usen et_0...@chezphi l.orgwrote:
>Dear Experts,
I need a function that takes a float, swaps its endianness (htonl) in place, and returns a char* pointer to its first byte. This is one of a family of functions that prepare different data types for passing to another process.
I have got confused by the rules about what won't work, what will work, and what might work, when casting. Specifically, I have an implementati on that works until I remove my debugging, at which point the compiler seems to decide that it can optimise away the writes to the bytes other than the first, or something like that. Here it is:
template <typename T> inline const char* encode_arg(T& t); // linker error if you try to // encode a type for which there // is no implementation
// This one works: template <> inline const char* encode_pq_arg<i nt>(int& i) { i = htonl(i); return reinterpret_cas t<const char*>(&i);
}
// This one doesn't: template <> inline const char* encode_arg<floa t>(float& f) { uint32_t* ptr = reinterpret_cas t<uint32_t*>(&f ); *ptr = htonl(*ptr); const char* cptr = reinterpret_cas t<const char*>(ptr); return cptr;
}
And it shouldn't. The encode_arg() function is effectively returning a
pointer to a local variable (the parameter f).
A pointer to the argument 'f'? You mean the address of it? The arg
is a reference. The address of a reference is the address of the
referenced object. Nothing is destroyed. Please revise your analysis.
So the caller of
encode_arg() receives a pointer to an object that no longer exists;
and therefore the value of the bytes obtained by dereferencing the
returned pointer - could be anything.
Greg
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: dgaucher |
last post by:
Hi,
I want to consume a Web Service that returns a choice, but my C++ client
always receives the same returned type. On the other hand, when I am using a
Java client, it is working fine (of course, the generated proxy is not the
same).
When I am looking at the C++ generated code, it seems fine, but when I am
executing the code, I always get the first choice type.
|
by: Jason Cartwright |
last post by:
I have an abstract base class and two derived classes that I want to
serialize and deserialize with schema validation. When I serialize
instances of the derived classes the XmlSerializer adds the
xsi:type="DerivedClass" attribute and the Instance Namespace. When I
attempt to validate the xml upon deserialization the
XmlValidatingReader chokes on this attribute value. I can't seem to
find a way around this. Any suggestions?
|
by: E. Robert Tisdale |
last post by:
What is an object?
Where did this term come from?
Does it have any relation
to the objects in "object oriented programming"?
|
by: S.Tobias |
last post by:
I'm trying to understand how structure type completion works.
# A structure or union type of unknown
# content (as described in 6.7.2.3) is an incomplete type. It
# is completed, for all declarations of that type, by
^^^
# declaring the same structure or union tag with its defining
# content later in the same scope.
^^^^^
(6.2.5#23)
|
by: Mike in Paradise |
last post by:
I have an application that is being passed objects which could either be an instance or a Type in the case of a Static Class
When you do the GetType on the object that was originally a Static class it gives you a type of "System.RuntimeType" as opposed to the orignal Static Class Typ
How do you get access to what type the the Orginal Static Class type was from the RuntimeType??
//Eg Routine......
Object objects = new Object
Class1...
| |
by: Rob Griffiths |
last post by:
Can anyone explain to me the difference between an element type and a
component type?
In the java literature, arrays are said to have component types, whereas
collections from the Collections Framework are said to have an element
type.
http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html
|
by: john |
last post by:
Hi to All
To demonstrate:
public class MyBaseGenericClass<T>
{
}
public class MyGenericClass1<T: MyBaseGenericClass<T>
{
|
by: Sky |
last post by:
I have been looking for a more powerful version of GetType(string) that will
find the Type no matter what, and will work even if only supplied
"{TypeName}", not the full "{TypeName},{AssemblyName}"
As far as I know yet -- hence this question -- there is no 'one solution
fits all', but instead there are several parts that have to be put together
to check.
What I have so far is, and would like as much feedback as possible to ensure
I've...
|
by: JH |
last post by:
Hi
I found that a type/class are both a subclass and a instance of base
type "object".
It conflicts to my understanding that:
1.) a type/class object is created from class statement
2.) a instance is created by "calling" a class object.
|
by: amanjsingh |
last post by:
Hi, I am trying to implement Java Web Service using Apache Axis2 and Eclipse as a tool. I have created the basic code and deployed the service using various eclipse plugin but when I try to invoke the service using client stub, I get this error...
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
org.apache cannot be resolved to a type
org.apache cannot be resolved to a type
org.apache cannot be resolved to a...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
| |
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |