Skip to content

Commit

Permalink
BUG: Fixes crashing issues on macOS Xcode 16 in debug mode.
Browse files Browse the repository at this point in the history
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 <[email protected]>BUG
  • Loading branch information
imikejackson committed Nov 18, 2024
1 parent d14bf1a commit be63bf8
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 63 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
79 changes: 46 additions & 33 deletions Source/EbsdLib/Core/EbsdLibConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <cstdint>
#include <string>

Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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
{
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 T>
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.
Expand All @@ -48,23 +48,23 @@ class BasicStringLiteral
* @return
*/
template <size_t Size>
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.
Expand Down Expand Up @@ -133,86 +133,93 @@ class BasicStringLiteral
};

template <class T>
bool operator==(const std::basic_string<T>& lhs, BasicStringLiteral<T> rhs)
bool operator==(const std::basic_string<T>& lhs, BasicEbsdStringLiteral<T> rhs)
{
return lhs == rhs.view();
}

template <class T>
bool operator==(BasicStringLiteral<T> lhs, const std::basic_string<T>& rhs)
bool operator==(BasicEbsdStringLiteral<T> lhs, const std::basic_string<T>& rhs)
{
return rhs == lhs;
}

template <class T>
bool operator!=(const std::basic_string<T>& lhs, BasicStringLiteral<T> rhs)
bool operator!=(const std::basic_string<T>& lhs, BasicEbsdStringLiteral<T> rhs)
{
return lhs != rhs.view();
}

template <class T>
bool operator!=(BasicStringLiteral<T> lhs, const std::basic_string<T>& rhs)
bool operator!=(BasicEbsdStringLiteral<T> lhs, const std::basic_string<T>& rhs)
{
return rhs != lhs;
}

template <class T>
bool operator<(const std::basic_string<T>& lhs, BasicStringLiteral<T> rhs)
bool operator<(const std::basic_string<T>& lhs, BasicEbsdStringLiteral<T> rhs)
{
return lhs < rhs.view();
}

template <class T>
bool operator<(BasicStringLiteral<T> lhs, const std::basic_string<T>& rhs)
bool operator<(BasicEbsdStringLiteral<T> lhs, const std::basic_string<T>& rhs)
{
return lhs.view() < rhs;
}

template <class T>
bool operator>(const std::basic_string<T>& lhs, BasicStringLiteral<T> rhs)
bool operator>(const std::basic_string<T>& lhs, BasicEbsdStringLiteral<T> rhs)
{
return lhs > rhs.view();
}

template <class T>
bool operator>(BasicStringLiteral<T> lhs, const std::basic_string<T>& rhs)
bool operator>(BasicEbsdStringLiteral<T> lhs, const std::basic_string<T>& rhs)
{
return lhs.view() > rhs;
}

template <class T>
bool operator<=(const std::basic_string<T>& lhs, BasicStringLiteral<T> rhs)
bool operator<=(const std::basic_string<T>& lhs, BasicEbsdStringLiteral<T> rhs)
{
return lhs <= rhs.view();
}

template <class T>
bool operator<=(BasicStringLiteral<T> lhs, const std::basic_string<T>& rhs)
bool operator<=(BasicEbsdStringLiteral<T> lhs, const std::basic_string<T>& rhs)
{
return lhs.view() <= rhs;
}

template <class T>
bool operator>=(const std::basic_string<T>& lhs, BasicStringLiteral<T> rhs)
bool operator>=(const std::basic_string<T>& lhs, BasicEbsdStringLiteral<T> rhs)
{
return lhs >= rhs.view();
}

template <class T>
bool operator>=(BasicStringLiteral<T> lhs, const std::basic_string<T>& rhs)
bool operator>=(BasicEbsdStringLiteral<T> lhs, const std::basic_string<T>& rhs)
{
return lhs.view() >= rhs;
}

using StringLiteral = BasicStringLiteral<char>;
using WStringLiteral = BasicStringLiteral<wchar_t>;
using String16Literal = BasicStringLiteral<char16_t>;
using String32Literal = BasicStringLiteral<char32_t>;
template <class T>
std::ostream& operator<<(std::ostream& os, const BasicEbsdStringLiteral<T>& lhs)
{
os << lhs.view();
return os;
}

using EbsdStringLiteral = BasicEbsdStringLiteral<char>;
using WEbsdStringLiteral = BasicEbsdStringLiteral<wchar_t>;
using String16Literal = BasicEbsdStringLiteral<char16_t>;
using String32Literal = BasicEbsdStringLiteral<char32_t>;
} // namespace EbsdLib

#if 0
template <class CharT>
struct fmt::formatter<nx::core::BasicStringLiteral<CharT>>
struct fmt::formatter<nx::core::BasicEbsdStringLiteral<CharT>>
{
static constexpr const CharT* GetFormatString()
{
Expand All @@ -239,7 +246,7 @@ struct fmt::formatter<nx::core::BasicStringLiteral<CharT>>
return ctx.begin();
}

typename buffer_context<CharT>::iterator format(const nx::core::BasicStringLiteral<CharT>& p, buffer_context<CharT>& ctx) const
typename buffer_context<CharT>::iterator format(const nx::core::BasicEbsdStringLiteral<CharT>& p, buffer_context<CharT>& ctx) const
{
static constexpr const CharT* formatStr = GetFormatString();

Expand Down
1 change: 1 addition & 0 deletions Source/EbsdLib/Core/SourceList.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit be63bf8

Please sign in to comment.