此代码是关于。
比赛条件: 调度和编译器行为在进程或线程同步中发挥重要作用。演示同步需求的最简单方案来自两个线程/进程之间创建的竞争条件,试图修改共享变量的值,这通常会导致数据不一致和错误的结果。以下示例演示了这种情况:
我是C的新手,我遇到了这个警告发生的问题。警告意味着什么,我该如何解决它。我写的代码在这里:
q1.c: In function ‘runner’:
q1.c:13:1: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long int’ [-Wformat=]
printf("T tid: %d x before: %d\n", syscall(SYS_gettid),x); int i;
^
q1.c:19:1: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long int’ [-Wformat=]
printf("T tid: %d x after: %d\n", syscall(SYS_gettid),x);
以下是代码:
// Race condition
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/syscall.h>
int x=0;
void * runner(void *arg)
{
printf("T tid: %d x before: %d\n", syscall(SYS_gettid),x); int i;
for (i = 0; i < 100000; i++ )
{
x = x + 1;
}
printf("T tid: %d x after: %d\n", syscall(SYS_gettid),x);
}
int program()
{
pthread_t t1,t2,t3,t4;
printf("Parent pid: %d x before threads: %d\n", getpid(),x); int i;
if(pthread_create(&t1,NULL, runner, NULL)){ printf("Error creating thread 1\n"); return 1;
}
if(pthread_create(&t2,NULL, runner, NULL)){ printf("Error creating thread 2\n"); return 1;
}
if(pthread_create(&t3,NULL, runner, NULL)){ printf("Error creating thread 1\n"); return 1;
}
if(pthread_create(&t4,NULL, runner, NULL)){ printf("Error creating thread 1\n"); return 1;
}
if(pthread_join(t1,NULL)){ printf("error joining thread 1"); return 1;
}
if(pthread_join(t2,NULL)){ printf("error joining thread 1"); return 1;
}
if(pthread_join(t3,NULL)){ printf("error joining thread 1"); return 1;
}
if(pthread_join(t4,NULL)){ printf("error joining thread 1"); return 1;
}
printf("Parent pid: %d x after threads: %d\n", getpid(),x); return 0;
}
int main(int argc, char *argv[]) {
int count=0;
// loop runs the program count times
while(count<5)
{
// running program program();
count++;
//reset global x for next run of program. x=0;
printf("\n\n");
}
return 0;
}
答案 0 :(得分:10)
您必须使用"%d"
更改"%ld"
,"%d"
更改为已签名int
,此处l
代表long
所以{{ 1}}用于签名"%ld"
。
答案 1 :(得分:0)
代码应始终以人类想要阅读的方式编写。 即使是作者在阅读代码时也存在重大问题 如许多“复制并粘贴”错误所示
注意:当一行开始'//'注释时,该行的其余部分都是注释
除main之外的任何函数都应该有原型。 在调用它们的任何函数之前声明被调用函数的方法 将适用于琐碎的程序,但不适用于多文件程序 具有交叉呼叫路径的程序 I.E.总是提供原型声明。
在调用某些功能时,请务必知道(I.E.查找)完整的详细信息 关于那个功能。在OPs发布代码的情况下, 这尤其适用于syscall()函数。
编写线程时,除了原型之外还有更多要知道的东西 一个线程。如在OPs代码中,还需要知道如何退出线程
始终在编译时启用所有警告。警告是问题 在继续之前应该修复的代码中。
BTW:使用单个互斥锁可以消除竞争条件问题// Race condition
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/syscall.h>
void *runner( void * );
int program( void );
int x=0;
// <-- compiler raises warning about unused parameter
void * runner(void *arg)
{
// the returned value from the syscall is a long int
//printf("T tid: %d x before: %d\n",
printf("T tid: %ld x before: %d\n",
syscall(SYS_gettid),
x);
int i;
for (i = 0; i < 100000; i++ )
{
x = x + 1;
}
// <-- the returned value from syscall is a long int
//printf("T tid: %d x after: %d\n",
printf("T tid: %ld x after: %d\n",
syscall(SYS_gettid),
x);
// <-- this line missing, compiler raises warning
pthread_exit(NULL);
} // end function: runner
int program()
{
pthread_t t1,t2,t3,t4;
printf("Parent pid: %d x before threads: %d\n",
getpid(),
x);
//int i; // <-- this variable not used, results in compiler warning
if( pthread_create(&t1, NULL, runner, NULL) )
{
printf("Error creating thread 1\n");
return 1;
}
if( pthread_create(&t2, NULL, runner, NULL) )
{
printf("Error creating thread 2\n");
return 1;
}
if( pthread_create(&t3, NULL, runner, NULL) )
{
// <-- copy and paste error
//printf("Error creating thread 1\n");
printf("Error creating thread 3\n");
return 1;
}
if( pthread_create(&t4, NULL, runner, NULL) )
{
// <-- copy and paste error
//printf("Error creating thread 1\n");
printf("Error creating thread 4\n");
return 1;
}
if( pthread_join(t1, NULL) )
{
printf("error joining thread 1");
return 1;
}
if( pthread_join(t2, NULL) )
{
// <-- copy and paste error
//printf("error joining thread 1");
printf("error joining thread 2");
return 1;
}
if( pthread_join(t3, NULL) )
{
// <-- copy and paste error
//printf("error joining thread 1");
printf("error joining thread 3");
return 1;
}
if( pthread_join(t4, NULL) )
{
// <-- copy and paste error
//printf("error joining thread 1");
printf("error joining thread 4");
return 1;
}
printf("Parent pid: %d x after threads: %d\n",
getpid(),
x);
return 0;
} // end function: program
// <-- this line cause compiler to raise two warnings about unused parameters
//int main(int argc, char *argv[])
int main()
{
int count=0;
// <-- there is no loop code perhaps you meant to put the 'while' on the next line
// loop runs the program count times while(count<5)
while( count < 5 )
{
// <-- program is not run, perhaps you meant to put the 'program()' on the next line
// running program program();
program();
count++;
// <-- x is not being reset, perhaps you menat to put 'x=0;' on the next line
//reset global x for next run of program. x=0;
x=0;
printf("\n\n");
}
return 0;
} // end function: main
答案 2 :(得分:0)
syscall()的原型返回long
#include <sys/syscall.h>
long syscall(long number, ...);
调用printf()
时,其格式说明符(如"%d"
)应与参数类型匹配(在参数通过可变参数的常规促销之后)。改为
v---- long --------v
v----------- int ----------v
printf("T tid: %ld x before: %d\n", syscall(SYS_gettid), x);