gpt4 book ai didi

valgrind - sem_open - valgrind 提示未初始化的字节

转载 作者:行者123 更新时间:2023-12-04 01:14:12 29 4
gpt4 key购买 nike

我有一个简单的程序:

int main(void)
{
const char sname[]="xxx";
sem_t *pSemaphor;
if ((pSemaphor = sem_open(sname, O_CREAT, 0644, 0)) == SEM_FAILED) {
perror("semaphore initilization");
exit(1);
}
sem_unlink(sname);
sem_close(pSemaphor);
}

当我在 valgrind 下运行它时,出现以下错误:
==12702== Syscall param write(buf) points to uninitialised byte(s)
==12702== at 0x4E457A0: __write_nocancel (syscall-template.S:81)
==12702== by 0x4E446FC: sem_open (sem_open.c:245)
==12702== by 0x4007D0: main (test.cpp:15)
==12702== Address 0xfff00023c is on thread 1's stack
==12702== in frame #1, created by sem_open (sem_open.c:139)

该代码是从一个更大的项目中提取的,它成功运行了多年,但现在它导致了段错误。

我的示例中的 valgrind 错误与在更大的项目中看到的相同,但它会导致崩溃,而我的小示例则没有。

最佳答案

我在 Debian 上用 glibc 2.27-5 看到了这一点。在我的情况下,我只在长时间运行的程序开始时打开信号量,到目前为止它似乎无害 - 只是烦人。

查看 sem_open.c 的代码,该代码位于:
https://code.woboq.org/userspace/glibc/nptl/sem_open.c.html

似乎 valgrind 正在提示这条线(我现在看起来是 270):

if (TEMP_FAILURE_RETRY (__libc_write (fd, &sem.initsem, sizeof (sem_t)))
== sizeof (sem_t)

然而 sem.initsem以一种相当巴洛克式的方式在早期正确初始化,首先通过在 sem.newsem 中显式设置字段(联合的一部分),然后通过调用 memset (L226-228) 完成:
  /* Initialize the remaining bytes as well.  */
memset ((char *) &sem.initsem + sizeof (struct new_sem), '\0',
sizeof (sem_t) - sizeof (struct new_sem));

我认为这个特殊的恶作剧都是非常理想的,但我们需要确保 new_sem 的所有字段实际上都已经初始化......我们在 https://code.woboq.org/userspace/glibc/sysdeps/nptl/internaltypes.h.html 中找到了定义。这是这个奇妙的创造:
struct new_sem
{
#if __HAVE_64B_ATOMICS
/* The data field holds both value (in the least-significant 32 bytes) and
nwaiters. */
# if __BYTE_ORDER == __LITTLE_ENDIAN
# define SEM_VALUE_OFFSET 0
# elif __BYTE_ORDER == __BIG_ENDIAN
# define SEM_VALUE_OFFSET 1
# else
# error Unsupported byte order.
# endif
# define SEM_NWAITERS_SHIFT 32
# define SEM_VALUE_MASK (~(unsigned int)0)
uint64_t data;
int private;
int pad;
#else
# define SEM_VALUE_SHIFT 1
# define SEM_NWAITERS_MASK ((unsigned int)1)
unsigned int value;
int private;
int pad;
unsigned int nwaiters;
#endif
};

所以如果我们 __HAVE_64B_ATOMICS那么结构有一个 data包含 value 的字段和 nwaiters ,否则这些是单独的字段。

sem.newsem 的初始化中我们可以看到这些被正确初始化,如下:
#if __HAVE_64B_ATOMICS
sem.newsem.data = value;
#else
sem.newsem.value = value << SEM_VALUE_SHIFT;
sem.newsem.nwaiters = 0;
#endif
/* pad is used as a mutex on pre-v9 sparc and ignored otherwise. */
sem.newsem.pad = 0;
/* This always is a shared semaphore. */
sem.newsem.private = FUTEX_SHARED;

我在 64 位系统上执行所有这些操作,所以我认为 valgrind 是在提示 64 位系统的初始化 sem.newsem.data使用 32 位 value从:
  value = va_arg (ap, unsigned int);

我们可以看到 value简单地定义为 unsigned int即使在 64 位系统上,它通常仍然是 32 位(参见 What should be the sizeof(int) on a 64-bit machine? ),但这应该只是在分配时隐式转换为 64 位。

所以我认为这不是错误 - 只是 valgrind 感到困惑。

关于valgrind - sem_open - valgrind 提示未初始化的字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35578095/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com