我有一个包含多个指针的结构。这些指针可以通过几个不同的线程来改变。这些线程通过更改指针使其指向另一个内存位置来更新结构,它们永远不会更改指向的值。根据我对volatile的理解,将struct中的这些指针声明为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;
}
答案 0 :(得分:3)
这是因为volatile int *
并不意味着“指向int的易失性指针”,它意味着“指向volatile int的指针”。比较const char *a = "foo";
,这是指向常量字符数据的指针,而不是常量指针。
所以在你的情况下,我认为thing
指针应该是volatile
,因为它中的字段可以“随机”改变(从一个线程的角度来看)。您可以(正如您在评论中所述)移动volatile
以使其在结构中成为int * volatile i;
。
你当然可以(当然)总是使用cdecl来获得即时帮助来解决这些问题。