From be63bf8abc4eb32668c506ba02db1ef11bf40976 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Mon, 18 Nov 2024 17:42:18 -0500 Subject: [PATCH] BUG: Fixes crashing issues on macOS Xcode 16 in debug mode. The bug is from some change in Xcode 16.x where using inline const std::string was causing cross translation unit initialization crashes (seg-fault). Signed-off-by: Michael Jackson BUG --- CMakeLists.txt | 2 +- Source/EbsdLib/Core/EbsdLibConstants.h | 79 +++++++++++-------- ...tringLiteral.hpp => EbsdStringLiteral.hpp} | 65 ++++++++------- Source/EbsdLib/Core/SourceList.cmake | 1 + 4 files changed, 84 insertions(+), 63 deletions(-) rename Source/EbsdLib/Core/{StringLiteral.hpp => EbsdStringLiteral.hpp} (64%) diff --git a/CMakeLists.txt b/CMakeLists.txt index f9309c5..b6229f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # set project's name -project(EbsdLibProj VERSION 1.0.35) +project(EbsdLibProj VERSION 1.0.36) # ---------- Setup output Directories ------------------------- set(CMAKE_LIBRARY_OUTPUT_DIRECTORY diff --git a/Source/EbsdLib/Core/EbsdLibConstants.h b/Source/EbsdLib/Core/EbsdLibConstants.h index e90acd5..5ae3ed3 100644 --- a/Source/EbsdLib/Core/EbsdLibConstants.h +++ b/Source/EbsdLib/Core/EbsdLibConstants.h @@ -33,8 +33,21 @@ * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +/** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * =======================> MAC OS WARNING <================================ + * Xcode 16 has changes specific to Apple systems where using a static const std::string variable + * inside of an inline function in this header will lead to executable crashes + * in Debug (but not release). This is why the use of StringLiteral was introduced. + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ #pragma once +#include "EbsdLib/Core/EbsdStringLiteral.hpp" + #include #include @@ -47,7 +60,7 @@ namespace EbsdLib using Rgb = uint32_t; inline constexpr Rgb RGB_MASK = 0x00ffffff; // masks RGB values -inline const std::string PathSep("|"); +inline constexpr EbsdStringLiteral PathSep("|"); inline constexpr uint8_t Unchecked = 0; inline constexpr uint8_t PartiallyChecked = 1; inline constexpr uint8_t Checked = 2; @@ -64,10 +77,10 @@ enum InfoStringFormat namespace StringConstants { -inline const std::string Statistics("Statistics"); -inline const std::string StatsData("StatsData"); -inline const std::string StatsType("StatsType"); -inline const std::string GBCD("GBCD"); +inline constexpr EbsdStringLiteral Statistics("Statistics"); +inline constexpr EbsdStringLiteral StatsData("StatsData"); +inline constexpr EbsdStringLiteral StatsType("StatsType"); +inline constexpr EbsdStringLiteral GBCD("GBCD"); } // namespace StringConstants namespace NumericTypes @@ -102,35 +115,35 @@ inline constexpr uint32_t UnknownRefFrameZDirection = 2; namespace H5Ebsd { -inline const std::string Manufacturer("Manufacturer"); -inline const std::string Header("Header"); -inline const std::string Phases("Phases"); -inline const std::string Phase("Phase"); -inline const std::string Data("Data"); -inline const std::string Index("Index"); +inline constexpr EbsdStringLiteral Manufacturer("Manufacturer"); +inline constexpr EbsdStringLiteral Header("Header"); +inline constexpr EbsdStringLiteral Phases("Phases"); +inline constexpr EbsdStringLiteral Phase("Phase"); +inline constexpr EbsdStringLiteral Data("Data"); +inline constexpr EbsdStringLiteral Index("Index"); -inline const std::string ZStartIndex("ZStartIndex"); -inline const std::string ZEndIndex("ZEndIndex"); -inline const std::string ZResolution("Z Resolution"); -inline const std::string StackingOrder("Stacking Order"); -inline const std::string SampleTransformationAngle("SampleTransformationAngle"); -inline const std::string SampleTransformationAxis("SampleTransformationAxis"); -inline const std::string EulerTransformationAngle("EulerTransformationAngle"); -inline const std::string EulerTransformationAxis("EulerTransformationAxis"); +inline constexpr EbsdStringLiteral ZStartIndex("ZStartIndex"); +inline constexpr EbsdStringLiteral ZEndIndex("ZEndIndex"); +inline constexpr EbsdStringLiteral ZResolution("Z Resolution"); +inline constexpr EbsdStringLiteral StackingOrder("Stacking Order"); +inline constexpr EbsdStringLiteral SampleTransformationAngle("SampleTransformationAngle"); +inline constexpr EbsdStringLiteral SampleTransformationAxis("SampleTransformationAxis"); +inline constexpr EbsdStringLiteral EulerTransformationAngle("EulerTransformationAngle"); +inline constexpr EbsdStringLiteral EulerTransformationAxis("EulerTransformationAxis"); // Each Manufacturer has their own naming scheme for these variables but for // DREAM.3D we are going to settle on using these names for consistency -inline const std::string XResolution("X Resolution"); -inline const std::string YResolution("Y Resolution"); +inline constexpr EbsdStringLiteral XResolution("X Resolution"); +inline constexpr EbsdStringLiteral YResolution("Y Resolution"); // We store the Maximum number of X and Y Points for the given volume. This // allows us to store slices that have different XY voxel dimensions. -inline const std::string XPoints("Max X Points"); -inline const std::string YPoints("Max Y Points"); +inline constexpr EbsdStringLiteral XPoints("Max X Points"); +inline constexpr EbsdStringLiteral YPoints("Max Y Points"); -inline const std::string FileVersionStr("FileVersion"); +inline constexpr EbsdStringLiteral FileVersionStr("FileVersion"); inline constexpr uint32_t FileVersion = 5; -inline const std::string EbsdLibVersionStr("EbsdLibVersion"); +inline constexpr EbsdStringLiteral EbsdLibVersionStr("EbsdLibVersion"); } // namespace H5Ebsd using EnumType = int32_t; @@ -149,8 +162,8 @@ enum class OEM : EnumType namespace CellData { -inline const std::string EulerAngles("EulerAngles"); -inline const std::string Phases("Phases"); +inline constexpr EbsdStringLiteral EulerAngles("EulerAngles"); +inline constexpr EbsdStringLiteral Phases("Phases"); } // namespace CellData enum EbsdToSampleCoordinateMapping @@ -163,9 +176,9 @@ enum EbsdToSampleCoordinateMapping namespace StackingOrder { -inline const std::string LowToHigh("Low To High"); -inline const std::string HighToLow("High To Low"); -inline const std::string UnknownStackingOrder("Unknown Stacking Order"); +inline constexpr EbsdStringLiteral LowToHigh("Low To High"); +inline constexpr EbsdStringLiteral HighToLow("High To Low"); +inline constexpr EbsdStringLiteral UnknownStackingOrder("Unknown Stacking Order"); namespace Utils { @@ -223,9 +236,9 @@ inline constexpr uint32_t UnknownCrystalStructure = 999; //!< UnknownCrystalStru namespace BravaisLattice { -inline const std::string Unknown("Unknown"); -inline const std::string Cubic("Cubic"); -inline const std::string Hexagonal("Hexagonal"); +inline constexpr EbsdStringLiteral Unknown("Unknown"); +inline constexpr EbsdStringLiteral Cubic("Cubic"); +inline constexpr EbsdStringLiteral Hexagonal("Hexagonal"); } // namespace BravaisLattice namespace AngleRepresentation diff --git a/Source/EbsdLib/Core/StringLiteral.hpp b/Source/EbsdLib/Core/EbsdStringLiteral.hpp similarity index 64% rename from Source/EbsdLib/Core/StringLiteral.hpp rename to Source/EbsdLib/Core/EbsdStringLiteral.hpp index 8de8508..ecfe562 100644 --- a/Source/EbsdLib/Core/StringLiteral.hpp +++ b/Source/EbsdLib/Core/EbsdStringLiteral.hpp @@ -25,21 +25,21 @@ constexpr bool HasNullTerminator(const T (&string)[Size]) noexcept } // namespace detail /** - * @brief BasicStringLiteral is meant to be a safe container for a string literal allowing for easy access to its size/length. + * @brief BasicEbsdStringLiteral is meant to be a safe container for a string literal allowing for easy access to its size/length. * This class should always contain a pointer to a static compile time null-terminated string literal. * Typical usage will be for static string constants. At this time the constructors allow non string literals to be passed in. * This is undesired behavior, but there is no way to overcome this in C++17 without using character parameter packs which come with their own issues. * Example: * @code - * static constexpr StringLiteral k_Foo = "foo"; + * static constexpr EbsdStringLiteral k_Foo = "foo"; * @endcode * @tparam T Character type */ template -class BasicStringLiteral +class BasicEbsdStringLiteral { public: - BasicStringLiteral() = delete; + BasicEbsdStringLiteral() = delete; /** * @brief Constructor that accepts a string literal of fixed size. Should be made consteval in C++20. @@ -48,23 +48,23 @@ class BasicStringLiteral * @return */ template - constexpr BasicStringLiteral(const T (&string)[Size]) + constexpr BasicEbsdStringLiteral(const T (&string)[Size]) : m_String(string) , m_Size(Size) { if(!detail::HasNullTerminator(string)) { - throw std::runtime_error("BasicStringLiteral must be null-terminated"); + throw std::runtime_error("BasicEbsdStringLiteral must be null-terminated"); } } - ~BasicStringLiteral() noexcept = default; + ~BasicEbsdStringLiteral() noexcept = default; - BasicStringLiteral(const BasicStringLiteral&) noexcept = default; - BasicStringLiteral(BasicStringLiteral&&) noexcept = default; + BasicEbsdStringLiteral(const BasicEbsdStringLiteral&) noexcept = default; + BasicEbsdStringLiteral(BasicEbsdStringLiteral&&) noexcept = default; - BasicStringLiteral& operator=(const BasicStringLiteral&) noexcept = default; - BasicStringLiteral& operator=(BasicStringLiteral&&) noexcept = default; + BasicEbsdStringLiteral& operator=(const BasicEbsdStringLiteral&) noexcept = default; + BasicEbsdStringLiteral& operator=(BasicEbsdStringLiteral&&) noexcept = default; /** * @brief Returns the c-string pointer. @@ -133,86 +133,93 @@ class BasicStringLiteral }; template -bool operator==(const std::basic_string& lhs, BasicStringLiteral rhs) +bool operator==(const std::basic_string& lhs, BasicEbsdStringLiteral rhs) { return lhs == rhs.view(); } template -bool operator==(BasicStringLiteral lhs, const std::basic_string& rhs) +bool operator==(BasicEbsdStringLiteral lhs, const std::basic_string& rhs) { return rhs == lhs; } template -bool operator!=(const std::basic_string& lhs, BasicStringLiteral rhs) +bool operator!=(const std::basic_string& lhs, BasicEbsdStringLiteral rhs) { return lhs != rhs.view(); } template -bool operator!=(BasicStringLiteral lhs, const std::basic_string& rhs) +bool operator!=(BasicEbsdStringLiteral lhs, const std::basic_string& rhs) { return rhs != lhs; } template -bool operator<(const std::basic_string& lhs, BasicStringLiteral rhs) +bool operator<(const std::basic_string& lhs, BasicEbsdStringLiteral rhs) { return lhs < rhs.view(); } template -bool operator<(BasicStringLiteral lhs, const std::basic_string& rhs) +bool operator<(BasicEbsdStringLiteral lhs, const std::basic_string& rhs) { return lhs.view() < rhs; } template -bool operator>(const std::basic_string& lhs, BasicStringLiteral rhs) +bool operator>(const std::basic_string& lhs, BasicEbsdStringLiteral rhs) { return lhs > rhs.view(); } template -bool operator>(BasicStringLiteral lhs, const std::basic_string& rhs) +bool operator>(BasicEbsdStringLiteral lhs, const std::basic_string& rhs) { return lhs.view() > rhs; } template -bool operator<=(const std::basic_string& lhs, BasicStringLiteral rhs) +bool operator<=(const std::basic_string& lhs, BasicEbsdStringLiteral rhs) { return lhs <= rhs.view(); } template -bool operator<=(BasicStringLiteral lhs, const std::basic_string& rhs) +bool operator<=(BasicEbsdStringLiteral lhs, const std::basic_string& rhs) { return lhs.view() <= rhs; } template -bool operator>=(const std::basic_string& lhs, BasicStringLiteral rhs) +bool operator>=(const std::basic_string& lhs, BasicEbsdStringLiteral rhs) { return lhs >= rhs.view(); } template -bool operator>=(BasicStringLiteral lhs, const std::basic_string& rhs) +bool operator>=(BasicEbsdStringLiteral lhs, const std::basic_string& rhs) { return lhs.view() >= rhs; } -using StringLiteral = BasicStringLiteral; -using WStringLiteral = BasicStringLiteral; -using String16Literal = BasicStringLiteral; -using String32Literal = BasicStringLiteral; +template +std::ostream& operator<<(std::ostream& os, const BasicEbsdStringLiteral& lhs) +{ + os << lhs.view(); + return os; +} + +using EbsdStringLiteral = BasicEbsdStringLiteral; +using WEbsdStringLiteral = BasicEbsdStringLiteral; +using String16Literal = BasicEbsdStringLiteral; +using String32Literal = BasicEbsdStringLiteral; } // namespace EbsdLib #if 0 template -struct fmt::formatter> +struct fmt::formatter> { static constexpr const CharT* GetFormatString() { @@ -239,7 +246,7 @@ struct fmt::formatter> return ctx.begin(); } - typename buffer_context::iterator format(const nx::core::BasicStringLiteral& p, buffer_context& ctx) const + typename buffer_context::iterator format(const nx::core::BasicEbsdStringLiteral& p, buffer_context& ctx) const { static constexpr const CharT* formatStr = GetFormatString(); diff --git a/Source/EbsdLib/Core/SourceList.cmake b/Source/EbsdLib/Core/SourceList.cmake index 49c73f9..e3fbb70 100644 --- a/Source/EbsdLib/Core/SourceList.cmake +++ b/Source/EbsdLib/Core/SourceList.cmake @@ -12,6 +12,7 @@ set(EbsdLib_${DIR_NAME}_HDRS ${EbsdLibProj_SOURCE_DIR}/Source/EbsdLib/${DIR_NAME}/OrientationRepresentation.h ${EbsdLibProj_SOURCE_DIR}/Source/EbsdLib/${DIR_NAME}/OrientationTransformation.hpp ${EbsdLibProj_SOURCE_DIR}/Source/EbsdLib/${DIR_NAME}/Quaternion.hpp + ${EbsdLibProj_SOURCE_DIR}/Source/EbsdLib/${DIR_NAME}/EbsdStringLiteral.hpp ) set(EbsdLib_${DIR_NAME}_SRCS