[英]Memory corruption when building (questionable) example with Clang instead of GCC
我有一些C代码,这些代码早在几年前就被快速“转换”为C ++代码,现在我维护它们。 在不同的操作系统上运行它并使用不同的编译器进行构建时,我注意到了一些特殊的行为,并且可以使用一些帮助来诊断我最近解决的一些问题。
该代码在以下系统上运行没有问题:
将其移植到以下系统后,一切就结束了:
令人反感的代码围绕以下结构展开:
struct blk_data {
int i;
int s;
boost::mutex protectionMutex;
};
有一段代码通过malloc()
创建此POD的动态实例(普通旧数据,无自定义方法或构造函数等malloc()
:
struct blk_data* pData = (blk_data*)malloc(16 * sizeof(struct blk_data));
if ( pData )
//...
请忽略我强制转换malloc()
结果的事实。 如果没有,编译器会标记错误。
稍后在代码中,我调用:
boost::unique_lock<boost::mutex> tempLock(pData->protectionMutex);
对于带有GCC的Linux,没有问题。 使用OSX和Clang,程序会出错,并指出最终传递给pthread_mutex_lock()
的互斥锁地址无效。 最终,我能够通过以下方式解决此问题:
new
代替malloc()
。 ${CXXFLAGS} += -std=c++11
其中,类似的问题会弹出一个第二个案例是使用代码块new
,但随后memset
荷兰国际集团的结构。 据我了解,只要使用POD struct
,这是安全的。
为什么此代码可以在GCC / Linux上构建并正常运行,却可以构建但不能运行; 在Clang / OSX上? 难道一个struct
不再算作一个POD struct
,如果它包含RAII风格的成员,或已经违反了我的全部时间的C ++标准的一部分(即:未定义行为)? 还是在Clang vs GCC中进行了更严格的检查?
谢谢。
从malloc
的文档中:
分配未初始化存储的大小字节
因此,在初始化之前使用内存是不确定的行为。
它可以在GCC中工作,因为
运气好
glibc的实现细节,特别是glibc的malloc依赖于调用nmap
从系统分配新内存这一事实。 默认情况下,nmap将内存归零,以防止信息从一个进程泄漏到另一个进程。
此处的文档: http : //man7.org/linux/man-pages/man2/mmap.2.html
OSX的malloc有所不同(尽管文档并未明确是否初始化新内存): https : //developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/malloc.3.html
尽管我不确定boost::mutex
是否为POD,但malloc
仅分配内存,而不初始化对象,这使protectionMutex
未初始化。
尽管new
确保了boost::mutex
默认ctor被调用,并因此初始化了protectionMutex
。
[更新]检查boost互斥体的头文件 ,它在内部使用指针:
#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可以工作...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.