-
June 9th, 2016, 01:18 PM
#1
Acceptable use of undefined behavior
Hello! I'm relatively new to C++ but a long time SWE, seeking some advice on pointer casting.
In the code below, I'm accepting some buffer (1-byte aligned) and swapping bytes as if it's an array of int16s. (Full code has equivalent methods for 32 and 64 bit types.)
Code:
#if defined(__GNUC__) || defined(__clang__)
#define BSWAP_INTRINSIC_2(x) __builtin_bswap16(x)
#elif defined(__linux__)
#include <byteswap.h>
#define BSWAP_INTRINSIC_2(x) bswap_16(x)
#elif defined(_MSC_VER)
#include <intrin.h>
#define BSWAP_INTRINSIC_2(x) _byteswap_ushort(x);
#else
#define BSWAP_INTRINSIC_2(x) (x << 8) | (x >> 8)
#endif
char* data; // some char buffer
// For debugging:
int alignment = reinterpret_cast<uintptr_t>(data) % alignof(uint16_t);
std::cout << "aligned? " << alignment << "\n";
uint16_t* data16 = reinterpret_cast<uint16_t*>(data);
for (size_t i = 0; i < length_of_data16; i++) {
data16[i] = BSWAP_INTRINSIC_2(data16[i]);
}
Sometimes, the `data16` pointer is not 2-byte aligned. Nonetheless, all of the possible definitions of BSWAP_INTRINSIC_2 work (i.e. MSVC, g++, clang; byteswap.h's bswap_16; and the bit-shifting fall through). In the assembly I see the compilers emitting MOVDQU, so they clearly identify that this might not be aligned and they're handling it.
- As I understand, it's technically illegal to cast a char* to a uint16_t* without verifying alignment. Is that true?
- Because this code works, how bad is it to use it?
- Is there a way to make this legal without using memcpy/memmove/etc. (memory impact is too high for big buffers) and while still making use of the fast SSE instructions that are currently being used (e.g. PSHUFB)?
Thanks!
-
June 10th, 2016, 02:43 AM
#2
Re: Acceptable use of undefined behavior
Originally Posted by zbjornson
As I understand, it's technically illegal to cast a char* to a uint16_t* without verifying alignment. Is that true?
more precisely, it's perfectly legal to reinterpret_cast pointers of basically any type ( ignoring cv qualification ), but doing basically anything with the result ( aside casting it back to the original type provided they have proper alignment ) will give undefined behaviour
Originally Posted by zbjornson
Because this code works, how bad is it to use it?
undefined behavoir is not "bad" per se, it just means that anything can happen ( including the program running as expected ) as far as the c++ abstract machine is concerned.
But, if *you*/the compiler/cpu/etc... can guarantee that some operation on some specific condition has some specific behavior then you're ok and nothing 'bad' will happen.
So, concerning your original issue, it depends on where the code will run on, consult your target compiler/cpu manual to know. AFAIR, for x86-32/64 the code should be ok at the cost of some performance penalty in the non aligned case ...
-
June 10th, 2016, 03:47 AM
#3
Re: Acceptable use of undefined behavior
But, if *you*/the compiler/cpu/etc... can guarantee that some operation on some specific condition has some specific behavior then you're ok and nothing 'bad' will happen.
but note that behaviour that is not defined as part of the standard or not documented by the compiler supplier can change between compiler releases and should be tested with every compiler change.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
June 10th, 2016, 08:24 AM
#4
Re: Acceptable use of undefined behavior
Originally Posted by 2kaud
but note that behaviour that is not defined as part of the standard or not documented by the compiler supplier can change between compiler releases and should be tested with every compiler change.
indeed, a "not documented" behaviour does not look like a "guarantee" to me
by "guarantee" I meant things like posix/winapi multithreading in pre-c++11, platform specific ABIs etc ...
Originally Posted by zbjornson
Is there a way to make this legal without using memcpy/memmove/etc. (memory impact is too high for big buffers) and while still making use of the fast SSE instructions that are currently being used (e.g. PSHUFB)?
BTW, I'm no SIMD expert, but given, say, a SIMD istruction operating on 16 bytes with a 2-byte UNaligned buffer, you could swap 14 bytes via that instruction and the remaining 2 bytes 'manually' ...
-
June 11th, 2016, 06:55 AM
#5
Re: Acceptable use of undefined behavior
Why take a chance? Wouldn't it be better to code something using 'defined' behavior so there is a reasonable chance that it will work continue to work in the future?
-
June 11th, 2016, 03:04 PM
#6
Re: Acceptable use of undefined behavior
Thanks all. Part of me was/is hoping that this in some way is not actually making use of UB and thus that it would be safe to do, since under the hood it's only doing byte-wise operations and not really interpreting int16s.
@superbonzo re: swapping 14 bytes on the alignment with SSE instructions and then 2 bytes, possible, although then I would have to write out the correct xmm2 (shuffle control mask) for each possible alignment and I couldn't make use of the simple built-ins. It would probably be easier to write out the assembly based on MOVDQU and PSHUFB .
@Arjay entirely speed. It's sad to take a 6x performance hit to use defined behavior when the code works (with the three different compilers that the project is required to build with, even).
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|