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 19, 2024
1 parent d14bf1a commit 0f73dd2
Show file tree
Hide file tree
Showing 5 changed files with 97 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
83 changes: 50 additions & 33 deletions Source/EbsdLib/Core/EbsdLibConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,25 @@
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

/** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* =======================> 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.
*
* EbsdStringLiteral are stack allocated instead of heap allocated. Which is Good.
*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
#pragma once

#include "EbsdLib/Core/EbsdStringLiteral.hpp"
#include "EbsdLib/EbsdLib.h"

#include <cstdint>
#include <string>

Expand All @@ -47,7 +64,7 @@ namespace EbsdLib

using Rgb = uint32_t;
inline constexpr Rgb RGB_MASK = 0x00ffffff; // masks RGB values
inline const std::string PathSep("|");
EbsdLib_macOS_NO_EXPORT 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 +81,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");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral Statistics("Statistics");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral StatsData("StatsData");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral StatsType("StatsType");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral GBCD("GBCD");
} // namespace StringConstants

namespace NumericTypes
Expand Down Expand Up @@ -102,35 +119,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");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral Manufacturer("Manufacturer");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral Header("Header");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral Phases("Phases");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral Phase("Phase");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral Data("Data");
EbsdLib_macOS_NO_EXPORT 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");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral ZStartIndex("ZStartIndex");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral ZEndIndex("ZEndIndex");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral ZResolution("Z Resolution");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral StackingOrder("Stacking Order");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral SampleTransformationAngle("SampleTransformationAngle");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral SampleTransformationAxis("SampleTransformationAxis");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral EulerTransformationAngle("EulerTransformationAngle");
EbsdLib_macOS_NO_EXPORT 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");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral XResolution("X Resolution");
EbsdLib_macOS_NO_EXPORT 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");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral XPoints("Max X Points");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral YPoints("Max Y Points");

inline const std::string FileVersionStr("FileVersion");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral FileVersionStr("FileVersion");
inline constexpr uint32_t FileVersion = 5;
inline const std::string EbsdLibVersionStr("EbsdLibVersion");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral EbsdLibVersionStr("EbsdLibVersion");
} // namespace H5Ebsd

using EnumType = int32_t;
Expand All @@ -149,8 +166,8 @@ enum class OEM : EnumType

namespace CellData
{
inline const std::string EulerAngles("EulerAngles");
inline const std::string Phases("Phases");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral EulerAngles("EulerAngles");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral Phases("Phases");
} // namespace CellData

enum EbsdToSampleCoordinateMapping
Expand All @@ -163,9 +180,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");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral LowToHigh("Low To High");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral HighToLow("High To Low");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral UnknownStackingOrder("Unknown Stacking Order");

namespace Utils
{
Expand Down Expand Up @@ -223,9 +240,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");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral Unknown("Unknown");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral Cubic("Cubic");
EbsdLib_macOS_NO_EXPORT inline constexpr EbsdStringLiteral Hexagonal("Hexagonal");
} // namespace BravaisLattice

namespace AngleRepresentation
Expand Down
9 changes: 9 additions & 0 deletions Source/EbsdLib/Core/EbsdLibDLLExport.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ building on Windows.
#define EbsdLib_EXPORT __attribute__((visibility("default")))
#endif
#endif

#if !defined(EbsdLib_macOS_NO_EXPORT)
#if defined(__APPLE__)
#define EbsdLib_macOS_NO_EXPORT __attribute__((visibility("hidden")))
#else
#define EbsdLib_macOS_NO_EXPORT
#endif
#endif

#endif

/* If EbsdLib_EXPORT was never defined, define it here */
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 0f73dd2

Please sign in to comment.