我有一个结构体,保存着多个指针。这些指针可以被不同的线程改变。这些线程通过将指针指向另一个内存位置而更新结构体,它们永远不会改变所指向的值。根据我对volatile的理解,在结构体中声明这些指针为volatile是有意义的。
读取/更新这些指针的线程的工作方式如下:
1. 复制指针, 只使用我们的副本, 这样如果原始指针更改了, 我们就不会在处理过程中突然使用新的指针。 2. 基于我们的副本指针指向的值创建一个新的指针。 3. 使用原子比较+交换(replace)旧指针和新指针, 除非另一个线程已经更新了它。
我遇到的问题是,当我复制指针时,我得到了一个警告:
"warning: initialization discards 'volatile' qualifier from pointer target type"
编译后的代码似乎可以正常工作,但警告让我感到困扰。我是否错误地使用了volatile?假设我的volatile使用正确,我该如何删除警告?我不想在复制指针的声明中添加volatile,因为没有其他线程会更新我们的副本,所以它真的不是volatile。只有在读取/写入结构体时才是volatile。
这里有一些演示我的问题的演示代码,我正在处理的实际代码要好得多,但也太大了无法发布。现在存在一个明显的内存泄漏,请忽略它,我的实际用例可以正确地跟踪和管理内存。我只关心这个问题中的“volatile”,我不想解决演示中的错误。
代码如下:
读取/更新这些指针的线程的工作方式如下:
1. 复制指针, 只使用我们的副本, 这样如果原始指针更改了, 我们就不会在处理过程中突然使用新的指针。 2. 基于我们的副本指针指向的值创建一个新的指针。 3. 使用原子比较+交换(replace)旧指针和新指针, 除非另一个线程已经更新了它。
我遇到的问题是,当我复制指针时,我得到了一个警告:
"warning: initialization discards 'volatile' qualifier from pointer target type"
编译后的代码似乎可以正常工作,但警告让我感到困扰。我是否错误地使用了volatile?假设我的volatile使用正确,我该如何删除警告?我不想在复制指针的声明中添加volatile,因为没有其他线程会更新我们的副本,所以它真的不是volatile。只有在读取/写入结构体时才是volatile。
这里有一些演示我的问题的演示代码,我正在处理的实际代码要好得多,但也太大了无法发布。现在存在一个明显的内存泄漏,请忽略它,我的实际用例可以正确地跟踪和管理内存。我只关心这个问题中的“volatile”,我不想解决演示中的错误。
gcc -std=gnu99 -pthread test.c && ./a.out
test.c: In function ‘the_thread’:
test.c:22:25: warning: initialization discards ‘volatile’ qualifier from pointer target type [enabled by default]
代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
typedef struct {
volatile int *i;
} thing;
void init( thing *t ) {
t->i = malloc( sizeof( int ));
*(t->i) = 1;
}
void *the_thread( void *args ) {
thing *t = args;
for ( int i = 0; i < 100; i++ ) {
// This generates the 'volatile' warning. But I don't want to make
// *copy volatile since no other threads will ever change 'copy'.
// Is this incorrect usage, or do I just need to do something to remove
// the warning?
int *copy = t->i;
int *new = malloc( sizeof( int ));
*new = (*copy) + 1;
// Glaring memory leak as old x becomes unreachable, this is a demo,
// the real program this is for has the issue solved.
// We do not care if it succeeds or fails to swap for this demo.
__sync_bool_compare_and_swap( &(t->i), copy, new );
}
}
int main() {
thing t;
init( &t );
pthread_t a;
pthread_t b;
pthread_create( &a, NULL, the_thread, &t );
pthread_create( &b, NULL, the_thread, &t );
pthread_join( a, NULL );
pthread_join( b, NULL );
return 0;
}