memcpy() 函数是否是进程安全的?

8

我在网上查找了很久,但没有得到满意的答案。

memcpy是否线程安全?(在Windows系统中)

我的意思是,如果我使用一个单独的memcpy写入到在进程之间共享的内存区域(使用boost::shared_memory_object),然后尝试使用一个单独的memcpy从另一个进程中读取该区域,那么其中一个进程会自动被阻塞,直到写操作完成吗?我可以在哪里阅读相关信息?


线程和进程是不同的东西。 - user2357112
4个回答

12

memcpy通常是为了速度而编写的。它不会是线程安全的。如果您需要这个功能,您需要在临界区内执行memcpy调用或使用其他信号量机制。

take_mutex(&mutex);
memcpy(dst, src, count);
yield_mutex(&mutex);

1
是的,您应该使用自己的锁定机制。但这并不是因为memcpy线程不安全,而是因为您正在操作共享内存。 - not-a-user
@temple: 没有手册上说它是的,所以它就不是 :) http://linux.die.net/man/3/memcpy - Drakosha
这个答案是不正确的。在Windows中,有C运行时库是线程安全的(https://dev59.com/AnE95IYBdhLWcg3wheNR)。在Solaris下,memcpy是线程安全的。 - Mustafa Ozturk
答案是正确的。如果您查看MSVC运行时的源代码,您会非常清楚地看到memcpy()不进行同步。仅仅因为Solaris恰好有一个线程安全的memcpy()并不意味着所有实现都会有,因为未指定memcpy()是否线程安全。因此,任何值得称道的程序员都会假设memcpy()不是线程安全的,并用互斥锁来保护它。 - John Källén
2
"thread safe" 和 "线程安全" 之间存在混淆。您可以从不同的线程调用 memcpy 而不会出现问题。但是,您可以滥用线程安全的 memcpy 来创建数据竞争,然后所有可能性都不存在了。这显然是调用者想要做的事情。 - gnasher729

6

memcpy不是线程/进程安全的


有趣,我本来猜想相反的结果。你有参考资料吗? - not-a-user
顺便问一下,“进程安全”是什么意思?我认为这意味着我可以同时在两个不同的进程中调用memcpy。这应该是显然的,因为不同的进程实际上有自己的memcpy副本,就像它们拥有任何其他函数的副本一样。(或者至少在共享C库的情况下,操作系统保证行为与每个进程拥有自己的副本时相同。) - not-a-user
实际上,不安全的是访问共享资源,例如从不同进程访问文件-但这并不意味着openreadwrite不是进程安全的。(无论如何,我怎么通知initexplorer.exe,我现在要调用write?) - not-a-user
@not-a-user:看一下原始问题和答案,那会解释他们所说的线程/进程安全。你关于资源的想法是正确的,那确实是个问题 :)。 - Drakosha

4

像memcpy()(或memmove())这样的例程是标准C库的一部分,通过标准的<string.h>头文件包含,并且对任何锁定机制一无所知。锁定应该由某种外部方式提供,比如进程间互斥、信号量或类似的东西。


4
您混淆了"原子性"和"线程安全"。如果您在共享区域并发读写数据(使用或不使用memcpy),那是不安全的。但当然,复制数据本身是线程安全的。
memcpy本身也是线程安全的,至少在POSIX系统上是这样的,请参见这个链接,因此我猜想它在Windows上也适用。其他情况会使其变得相当无用。
如果它是"自动阻塞"的,它就必须是原子性的(或至少管理自己的锁),这会减慢系统速度。所以在您的情况下,应该使用您自己的锁。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接