使用Clang而不是GCC构建(可疑)示例时内存损坏 我有一些C代码,它很快被“转换”成C++代码,我现在保存。我注意到在不同的操作系统上运行它,并使用不同的编译器构建它时,会出现一些特殊的行为,可能需要一些帮助来诊断我最近解决的一些问题

使用Clang而不是GCC构建(可疑)示例时内存损坏 我有一些C代码,它很快被“转换”成C++代码,我现在保存。我注意到在不同的操作系统上运行它,并使用不同的编译器构建它时,会出现一些特殊的行为,可能需要一些帮助来诊断我最近解决的一些问题,c++,macos,c++11,gcc,boost,C++,Macos,C++11,Gcc,Boost,代码在以下系统上无问题运行: Ubuntu 14.04.2 LTS x64 通用条款4.8.4 将其移植到以下系统后,情况变得更糟: OSX“El Capitan” 苹果LLVM 7.3.0版(clang-703.0.29) 违规代码围绕以下结构展开: struct blk_data { int i; int s; boost::mutex protectionMutex; }; 有一段代码,其中通过malloc()创建了此POD的动态实例(纯旧数据,没有自定

代码在以下系统上无问题运行:

  • Ubuntu 14.04.2 LTS x64
  • 通用条款4.8.4
将其移植到以下系统后,情况变得更糟:

  • OSX“El Capitan”
  • 苹果LLVM 7.3.0版(clang-703.0.29)

违规代码围绕以下结构展开:

struct blk_data {
    int i;
    int s;
    boost::mutex protectionMutex;
};
有一段代码,其中通过
malloc()
创建了此POD的动态实例(纯旧数据,没有自定义方法或构造函数等):

请忽略我正在投射
malloc()
结果的事实。如果我没有,编译器会标记一个错误

稍后在代码中,我调用:

boost::unique_lock<boost::mutex> tempLock(pData->protectionMutex);
boost::唯一锁模板锁(pData->protectionMutex);
对于带有GCC的Linux,没有问题。对于OSX和Clang,程序会出错,注意到最终传递到
pthread\u mutex\u lock()
的互斥地址无效。最终,我通过以下方式解决了这个问题:

  • 使用
    new
    而不是
    malloc()
  • 设置
    ${CXXFLAGS}+=-std=c++11
出现类似问题的第二种情况是使用
new
的一块代码,但随后
memset
将该结构拆分。据我所知,只要使用POD
struct
,这是安全的

为什么这段代码在GCC/Linux上构建和运行良好,但它构建了,但没有运行;在叮当声/OSX上?如果包含RAII样式成员,那么<代码>结构Stuts<代码>不再被计算为POD <代码>结构> /代码>,或者我违反了C++标准的一部分(即:未定义行为)?或者这是一个在Clang和GCC中进行更严格检查的案例


谢谢。

来自
malloc
的文档:

struct blk_data* pData = (blk_data*)malloc(16 * sizeof(struct blk_data));
if ( pData )
//...
分配未初始化存储的大小字节

因此,在初始化之前使用内存是未定义的行为

它在GCC中工作是因为glibc的一个实现细节,特别是glibc的malloc遵从对
nmap
的调用来从系统分配新内存。默认情况下,nmap将清空内存,以防止信息从一个进程泄漏到另一个进程

此处的文档:

OSX的malloc不同(尽管文档没有明确说明新内存是否初始化):
来自
malloc
的文档:

struct blk_data* pData = (blk_data*)malloc(16 * sizeof(struct blk_data));
if ( pData )
//...
分配未初始化存储的大小字节

因此,在初始化之前使用内存是未定义的行为

它在GCC中工作是因为glibc的一个实现细节,特别是glibc的malloc遵从对
nmap
的调用来从系统分配新内存。默认情况下,nmap将清空内存,以防止信息从一个进程泄漏到另一个进程

此处的文档:

OSX的malloc不同(尽管文档没有明确说明新内存是否初始化):
虽然我不确定
boost::mutex
是否为POD,但
malloc
只分配内存,不初始化对象,这使得
protectionMutex
未初始化

new
确保调用
boost::mutex
的默认ctor,从而初始化
protectionMutex

[更新]检查boost mutex,它在内部使用指针:

#if defined(BOOST_HAS_WINTHREADS)
    typedef void* cv_state;
#elif defined(BOOST_HAS_PTHREADS)
    struct cv_state
    {
        pthread_mutex_t* pmutex;
    };
#elif defined(BOOST_HAS_MPTASKS)
    struct cv_state
    {
    };
#endif
因此
malloc
肯定不会初始化指针,而
new
会初始化指针


但我真的不知道GCC为什么能工作…

虽然我不确定
boost::mutex
是否为POD,但
malloc
只分配内存,不初始化对象,这使得
protectionMutex
未初始化

new
确保调用
boost::mutex
的默认ctor,从而初始化
protectionMutex

[更新]检查boost mutex,它在内部使用指针:

#if defined(BOOST_HAS_WINTHREADS)
    typedef void* cv_state;
#elif defined(BOOST_HAS_PTHREADS)
    struct cv_state
    {
        pthread_mutex_t* pmutex;
    };
#elif defined(BOOST_HAS_MPTASKS)
    struct cv_state
    {
    };
#endif
因此
malloc
肯定不会初始化指针,而
new
会初始化指针


但我真的不知道GCC为什么工作…

互斥体不是由其构造函数初始化的,不能得到更多的UB。
blk_数据
如果包含一个非POD成员就不是POD-我确信
boost::mutex
不是POD。是
boost::mutex
POD吗?@我最肯定不是。只检查了boost::mutex头,它在内部使用一个指针,所以它不是POD。互斥体不是由它的构造函数初始化的,不能得到更多的UB。如果它包含一个非POD成员,
blk_data
不是POD-我确信
boost::mutex
不是POD。是
boost::mutex
POD吗?@我最肯定不是。只检查了boost::mutex头,它在内部使用指针,因此不是POD。