使用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
将该结构拆分。据我所知,只要使用PODstruct
,这是安全的
为什么这段代码在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。