【发布时间】:2020-09-30 20:57:35
【问题描述】:
以下代码使用 Posix Memalign 为每个内核分配四个缓冲区,每个缓冲区 128 字节。它在 Skylake 上成功,但在 Broadwell(较早一代)上失败,并显示以下消息:
posix memalign malloc.c:2401: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed
根据 Linux 手册页,memalign 在以下情况下会失败:(1) 对齐参数不是 2 的幂,或者不是 sizeof(void *) 的倍数,或者 (2) 不够内存以满足分配请求。由于它会产生分段错误,因此我无法从 rax 获取错误号。 Broadwell 有 8GB 内存,所以内存不足不是问题。对齐是 64,所以这不是问题,而且无论如何它在我的 Skylake 上成功,所以它写得正确。
以下是相关代码块:
mov rax,2 ; number of cores
mov rbx,4 ; number of buffers to create
mul rbx
mov r14,rax
xor r13,r13
Memalign_Create_Loop:
mov rax,r15 ; number of cores
mov rbx,r12 ; number of buffers needed
; N ptrs per core x 8 bytes per pointer
mul rbx ; times the number of cores
mov r12,rax ; number of buffers needed x number of cores
lea rdi,[memalign_pointer]
mov rsi,64 ; alignment
mov rdx,r12
shl rdx,3
mov rdx,128 ; buffer size
;xor rax,rax
sub rsp,40
call posix_memalign wrt ..plt
add rsp,40
lea r8,[internal_buffer_pointers]
lea rdi,[memalign_pointer]
mov rax,[rdi]
mov rbx,r13
shl rbx,3
mov [r8+rbx],rax
add r13,1
cmp r13,r14
jl Memalign_Create_Loop
它在“call posix_memalign wrt ..plt”处失败,并显示如上所示的错误消息以及分段错误消息。
这对我来说是个谜,因为它在 Skylake 上取得了成功,而且 posix_memalign 早于 Broadwell。
我组装并链接到:
sudo nasm -f elf64 -g -F dwarf NWL.asm
sudo ld -shared NWL.o /opt/P01_SH/_Library/Create_Threads_in_C-NWL.o /opt/P01_SH/_Library/Timer_for_NASM.o /opt/P01_SH/_Library/POSIX_Shared_Memory.o /opt/P01_SH/_Library/PThread_Mutex .o /opt/P01_SH/_Library/Create_Multi_Files.o -ldl -lrt -lpthread -lm -o NWL.so
感谢您对此提出任何想法。
【问题讨论】:
-
CPU 系列似乎不太可能成为决定性的特征。两台机器使用什么操作系统版本?另外,您使用什么命令来组装和链接? AFAIK plt 在 x86-64 上通常不需要;如果你只是
call posix_memalign,它可以工作吗? -
我一直在使用过程链接表,但是您建议没有它的调用是有道理的,因为这可能是 seg 错误的来源(包括调用中的 plt)。我用汇编和链接字符串(NASM 编译器和 ld 链接)更新了我的问题。要查询 Linux 版本并在没有 plt 的情况下尝试调用,它是一个共享服务器,大约 30 分钟我无法访问。之后,我可以在这里更新答案。感谢您的 cmets。
-
断言消息似乎表明存在堆损坏的情况。那么实际的错误将出现在早期的代码中,只有在您的函数尝试另一个分配时才会检测到损坏。两个 CPU 可能实现不同的向量指令集,并且许多高度优化的库具有针对每个 CPU 系列专门调整的代码,在运行时选择。这可能会导致不同大小的堆分配,而损坏只针对其中一种情况。
-
好点@kisch。您是否尝试过调试 malloc 崩溃的常用技术,例如瓦尔格林?
posix_memalign与malloc是同一条船,在这里你使用哪一个并不重要。这很可能是一个简单的错误,您只是在某处注销了内存块的末尾,或者在释放内存后使用了内存,与 CPU 架构的深奥细节或分配大块还是小块无关。 -
@PeterCordes:感谢您的澄清,在评论之前我没有比较 CPU。这使得与调整库不同的堆使用模式不太可能。在这种情况下,我可能会寻找不同数量的内核,这可能会遇到多线程错误。特别是因为发布的代码明确提到了核心的数量。
标签: linux memory memory-management posix x86-64