c - 将 mremap(..., MREMAP_FIXED) 与 valgrind 一起使用
问题描述
考虑这种实现包装缓冲区的方法:
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
static int wrapping_buffer(void)
{
char *b1, *b2;
long size;
size = sysconf(_SC_PAGE_SIZE);
if (size == -1) {
perror("_SC_PAGE_SIZE");
return 1;
}
b1 = mmap(NULL, 2 * size, PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_ANONYMOUS, -1, 0);
if (!b1) {
perror("mmap");
return 1;
}
memset(b1, 0, 2 * size);
/* This remaps the upper half of the buffer to the lower half,
The same memory is now accessed by 2 different virtual adresses */
b2 = mremap(b1, 0, size, MREMAP_MAYMOVE|MREMAP_FIXED, b1 + size);
if (b2 != b1 + size) {
perror("mremap");
return 1;
}
sprintf(b1 + size - 16, "this sentence is too long to fit in buffer");
printf("end:\t\"%s\"\n", b1 + size - 16);
printf("start:\t\"%s\"\n", b1);
if (munmap(b2, size) != 0)
perror("munmap(2)");
if (munmap(b1, 2 * size) != 0)
perror("munmap(1)");
return 0;
}
int main(void)
{
return wrapping_buffer();
}
该程序编译并产生如下输出
end: "this sentence is too long to fit in buffer"
start: " too long to fit in buffer"
IOW,写入缓冲区的超过一页大小的字符串被包装到缓冲区的开头。这是基于mremap(2)的记录行为:
如果 old_size 的值为零,并且 old_address 指的是可共享映射(请参阅 mmap(2) MAP_SHARED),则 mremap() 将创建相同页面的新映射。
不幸的是,如果我尝试在 valgrind 下运行这个程序,它会在mremap()
调用中失败:
==7217== Memcheck, a memory error detector
==7217== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7217== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==7217== Command: /tmp/wrapping_buffer
==7217==
mremap: Invalid argument
这意味着我不能在任何应该使用 valgrind 调试的程序中使用这种技术(不是在谈论这个特定的代码,而是在程序的其他可能包含内存泄漏的部分)。这很不幸,因为我真的很喜欢重映射技术的优雅和效率。
有谁知道如何在 valgrind 下进行这项工作?还是我必须为此破解 valgrind 本身?
解决方案
推荐阅读
- html - flex-wrap 不起作用,即使应用了 min-width
- sql - 多个加倍 JOIN 到同一个表
- azure-databricks - 在 DataBricks Notebook 中读取行值
- javascript - 在 ThreeJS 中使用一个 OrbitControls 和两个摄像头?
- bash - 当用户写EXIT时如何退出文本文件编辑模式?
- java - 在java类和服务中获取上下文
- python - 在有障碍物的迷宫中查找路径的数量
- bash - 在 ConEmu 中集成了 ZSH 的 WSL Bash - 在此处打开问题
- java - 卡在试图从 firebase 数据库中检索数据
- linked-list - 是否可以在 Rust 中将一个结构的内存与另一个结构相关联?