我在信号处理程序中调用了一些C++函数,但我的程序被分段错误终止。当我使用gdb进行检查时,memcpy()函数是我收到SIGSEGV的地方。我想知道memcpy()是否是可重入函数?
我在信号处理程序中调用了一些C++函数,但我的程序被分段错误终止。当我使用gdb进行检查时,memcpy()函数是我收到SIGSEGV的地方。我想知道memcpy()是否是可重入函数?
除了最高度嵌入式平台,它将是可重入的。您提到SIGSEGV,因此我假设这不是其中之一。在这种情况下,最有可能的是memcpy()不是罪魁祸首:而是调用者的问题。如果您要求memcpy()复制错误的指针(或错误的长度),那么它将是引发故障的函数。您可以轻松地这样做:
memcpy(NULL, NULL, 123456789);
这会导致SIGSEGV错误,并且它会告诉你是memcpy()引起的。当然,这并不是memcpy的错误 - 它只是在执行你告诉它要做的事情。你的信号处理程序正在使用一些奇怪的东西调用它。通过回溯(在gdb或任何你拥有的工具中),可以找到调用者的位置。如果失败了,就打印出你传递给memcpy的参数。
memcpy
的调用,看看是否仍会出现段错误。如果问题消失了,那么memcpy
就不是异步信号安全的。如果问题仍然存在,那么问题要么在于实际复制之外,要么涉及到char
访问不是信号原子性的微妙问题。 - Steve Jessopmemcpy
,否则我们只能依靠对实现可能性的直觉。我们知道这不是错误,但据我所知,这并非由Posix保证,glibc可能会提供保证。 - Steve Jessop关于(不)可重入函数和信号处理程序(与GNU C库相关的部分),可以在此处找到一些相关信息:
以下部分特别与您的问题相关:
"仅从内存对象中读取是安全的,前提是您能够处理可能在信号可以交付时出现在对象中的任何值。请记住,对某些数据类型的赋值需要多个指令,这意味着如果其类型不是原子的,则处理程序可能在变量的赋值“中间”运行。"
"仅向内存对象写入是安全的,只要在处理程序可能运行的任何时间更改值不会干扰任何内容。"
我不明白为什么它不能是可重入的。我不确定,但我认为这很大程度上取决于你使用的库。
除非memcpy
实现得很糟糕,否则它是可重入的。它只能使用你提供的指针和长度值。所有参数都是按值传递的,因此一旦函数被激活,这些值将不会在其堆栈帧上更改,无论信号和/或其他线程如何。
我认为问题在于您将无效(或已删除)指针作为memcpy函数的参数,请仔细检查您的代码。
此致敬礼。
memcpy
是安全的,但如果你做了类似于free(somestruct->data); somestruct->data = 0; somestruct->len = 0;
的操作,那么当然信号可能会在这个过程中发生。 - Steve Jessop