任何人都可以帮我理解下面的问题吗?
为什么sleep()导致静态变量不在调用之间保持其值?
注意:部分代码由多个线程调用 表演同样的事情。
以下是代码的一部分:
int get_value_agent(DC_ITEM *item, AGENT_RESULT *result)
{
const char *__function_name = "get_value_agent";
char *buf, buffer[MAX_STRING_LEN];
int ret = SUCCEED;
ssize_t received_len;
static char *test;
int i,j;
int sock;
struct sockaddr_in sin;
if (SUCCEED == (ret = tcpConnect(CONFIG_SOURCE_IP, item->interface.addr)))
{
zbx_snprintf(buffer, sizeof(buffer), "%s\n", item->key);
if ((test = sendViaSFTP(buffer, CONFIG_SOURCE_IP, item->interface.addr)) != "FAIL")
{
buf = recvViaSFTP(test);
while(!buf)
{
sleep(2);
buf = recvViaSFTP(test);
received_len = 1;
}
}
}
//
}
这里“test”是一个静态变量。 函数“recvViaSFTP(test)”被多次调用,直到它从客户端返回一些非空值。
执行sleep()后,再次调用函数recvViaSFTP(test)。但是我注意到这次,测试中存储的值变为NULL。
我怀疑在为其他线程分配CPU之后,变量“test”被其他线程(在休眠时)修改。但令人困惑的是,变量“缓冲区”即使在睡眠后也不会被修改。
有没有办法避免变量“test”的变化?如果它可以通过互斥锁实现,那么我可以在创建线程之后使用互斥锁吗?
我尝试了另一种方式。我删除了sleep()函数,发现test中存储的值没有改变。
对不起我的小解释,因为我认为这可能是一个着名的问题。
请回答如此解释的行为。
答案 0 :(得分:2)
它没有直接这样做。所有sleep()
都会挂起遇到sleep()
函数的线程。另一个线程可以修改静态变量。 (但是另一个线程无论如何都可以做到这一点;无论其他线程是否正在休眠)。
答案 1 :(得分:0)
C11内存模型表明数据争用是未定义的行为。每当您使用两个不同的线程访问相同的变量并且其中至少有一个是写入时,行为是未定义的。在你的情况下,test
上有一个数据竞争,这是一个奇怪的行为的一个很好的理由。使用互斥锁来保护对共享变量的每个并发访问。
此外,您使用的是__function_name
,这是一个保留的标识符,因为它以两个下划线开头。
答案 2 :(得分:0)
我终于实现了这种未定义行为的解决方案。这实际上不是"只是"由于比赛条件。我昨天在stackoverflow.com上经历了几个帖子并且在c(特别是)中学习了如果一个人返回像"字符数组"这样的局部变量。或"指向字符的指针"从一个函数到另一个函数,这个值很可能会丢失。
我还试图返回本地变量" test"在行:
if ((test = sendViaSFTP(buffer, CONFIG_SOURCE_IP, item->interface.addr)) != "FAIL")
在睡眠()之后总是丢失。
因此,我以这种方式从调用函数更改了代码:
void some_Function(){
............................
............................
do{
sendViaSFTP(buffer, item->interface.dns_orig, &test);
.........................
.........................
sleep(2);
buf = recvViaSFTP(test);
.........................
.........................
.........................
}while(!buf);
if(test){
free(test);
test = NULL;
}
}
void sendViaSFTP(const char *data, const char *pwd, char **ret)
{
...................
...................
...................
finalReturn = malloc((strlen(sftppath) + 1)*sizeof(char));
strncpy(finalReturn, sftppath, strlen(sftppath) + 1);
*ret = finalReturn;
}
我的意思是,我通过引用传递测试并将其内存写入所需的值。并且,结果是" test"永远不会丢失。