该问题涉及大量代码,因此我将尝试通过一些示例代码来大致了解发生了什么。如果有什么我似乎遗漏的,请发表评论,我会添加更多。无论如何,我有一个对象,其方法使用 openMP:
#pragma omp parallel
{
int num_thread = omp_get_thread_num();
// This function will allocate and deallocate memory through Mxcalloc and MxFree before returning
foo.get_foo(num_thread);
}
foo
类已在另一个文件中定义(该文件是使用 -C
标志编译的)并且已编译并链接到使用 openMP 的对象。它使用两种方法分配和释放内存:
void foo::alloc(const int &h, const int &w) {
if (value == NULL) {
width = w;
height = h;
value = (double *)mxCalloc(h*w,sizeof(double));
} else {
mexPrintf("Memory has already been allocated when attempting to alloc.\n");
}
}
void foo::free() {
if (value != NULL) {
width = 0;
height = 0;
mxFree(value);
value = NULL;
} else {
mexPrintf("Memory has not been allocated yet when attempting to free.\n");
}
}
代码在单线程中运行得非常好。但是,当使用多线程运行时,出现以下错误:
*** glibc detected *** /usr/local/MATLAB/R2013a/bin/glnxa64/MATLAB: double free or corruption (out): 0x00007f4118019d20 ***
*** glibc detected *** /usr/local/MATLAB/R2013a/bin/glnxa64/MATLAB: malloc(): memory corruption: 0x00007f4101120541 ***
*** glibc detected *** /usr/local/MATLAB/R2013a/bin/glnxa64/MATLAB: double free or corruption (out): 0x00007f412c011260 ***
*** glibc detected *** /usr/local/MATLAB/R2013a/bin/glnxa64/MATLAB: malloc(): memory corruption: 0x00007f4101120541 ***
现在,如果我删除所有 free
调用(随后删除所有 mxFree
调用),并重新编译/重新运行代码,它似乎工作正常(我觉得这很奇怪,因为对 mxFree
的调用仅在指针不为空时才会发生 - 所以我不知道问题是什么)。所以我将范围缩小到 mxFree
调用不是线程安全的。
我还尝试添加一个 critical
部分如下所示:
#pragma omp parallel
{
int num_thread = omp_get_thread_num();
// This function will allocate and deallocate memory through Mxcalloc and MxFree before returning
#pragma omp critical
{
foo.get_foo(num_thread);
}
}
并且代码仍然无法正常工作并导致类似的错误消息。所以我的问题是:是 mxFree
和 mxCalloc
完全非线程安全——因为它们只在被单个线程调用时工作,即使被其他线程独立调用(由 critical
部分保证),函数仍然会失败?我将不胜感激任何提示或建议。我在考虑也许只用 std::vectors
替换 mxCalloc 调用和 resize
但我想知道在更改一堆代码之前先发生了什么。
更新
我刚刚浏览了我的代码并将 vector 与 resize
一起使用代替 mxCalloc
和 mxFree
这解决了我遇到的所有问题。仅供将来引用,绝对避免在任何并行区域中使用 MEX API。即使你使用 critical
部分,它仍然会导致我的 linux 系统崩溃。这个问题实际上被掩盖了一段时间,因为这个问题没有发生在我使用 Windows 7 的笔记本电脑上。
最佳答案
C MEX API is not thread-safe .根据 MathWorks 支持团队的说法:
Since the MEX API is not thread safe, no MEX API functions can be used in the spawned threads...
但是,似乎一些 MEX API 函数have been made thread-safe ,例如 mexErrMsgIdAndTxt
。看来动态内存分配还在黑名单上。
代替 mxMalloc
和 mxCalloc
,使用 malloc
和 calloc
(或 new
和 delete[]
)。
关于c++ - MxCalloc 和 MxFree 与 OpenMP 结果双重释放或损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24085098/