Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 这个函数是完全线程安全的吗?_C_Multithreading_Thread Safety_Pthreads - Fatal编程技术网

C 这个函数是完全线程安全的吗?

C 这个函数是完全线程安全的吗?,c,multithreading,thread-safety,pthreads,C,Multithreading,Thread Safety,Pthreads,EDIT3:每次需要时,它都会在一个新线程中生成,“input”是一个在其中释放的char*的副本。假设cURL函数是线程安全的 static void *Com_GoogleTranslate(void* input) { CURL *easy_handle; char *pos1, *pos2, url[1024], final[1024], inlang[8], outlang[8], *encoded; const int const_strlen = strlen("\"tra

EDIT3:每次需要时,它都会在一个新线程中生成,“input”是一个在其中释放的char*的副本。假设cURL函数是线程安全的

static void *Com_GoogleTranslate(void* input) {

 CURL *easy_handle;
 char *pos1, *pos2, url[1024], final[1024], inlang[8], outlang[8], *encoded;
 const int const_strlen = strlen("\"translatedText\":\"");
 struct GoogleMem chunk;

 pthread_mutex_lock( &GoogleMessage_mutex );
  // 'auto' is really empty in google API:
  if (!strcmp(clu.translateIn->string, "auto"))  
   strcpy(inlang, "");
  else            
   strcpy(inlang, clu.translateIn->string);

  if (!strcmp(clu.translateOut->string, "auto")) 
   strcpy(outlang, "");
  else            
   strcpy(outlang, clu.translateOut->string);
 pthread_mutex_unlock( &GoogleMessage_mutex );

 // Build the URL
 url[0] = '\0';
 strcat(url, "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=");

 // Encode input into URL formatting
 encoded = url_encode((char*)input);
 if (!encoded) return 0;

 strcat(url, encoded);
 strcat(url, "&langpair=");
 strcat(url, inlang);
 strcat(url, "|");
 strcat(url, outlang);

 chunk.memory = malloc(1);  // realloc grows it at Com_GoogleTranslateMem()
 if (!chunk.memory) return 0;
 chunk.size = 0;    // no data yet

 // cURL initialization for this sub-session:
 easy_handle = qcurl_easy_init(); 

 // ioq3-urt: was needed on https:// (v2 API) attempts when using GnuTLS
 //qcurl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 3); 

 // set URL:
 qcurl_easy_setopt(easy_handle, CURLOPT_URL, url);

 // ioq3-urt: required for multithreading according to cURL doc.
 qcurl_easy_setopt(easy_handle, CURLOPT_NOSIGNAL, 1);

 // ioq3-urt: skip peer verification; required for google translate when SSL was used
 //qcurl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);

 // send all data to this function
 qcurl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, Com_GoogleTranslateMem);

 // we pass our 'chunk' struct to the callback function:
 qcurl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, (void *)&chunk);

 // some servers don't like requests that are made without a user-agent field, so we provide one:
 qcurl_easy_setopt(easy_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");

 // ioq3-urt: Required by Google Translate terms:
 qcurl_easy_setopt(easy_handle, CURLOPT_REFERER, "ioq3-urt");

 // fetch it
 qcurl_easy_perform(easy_handle);

 // cleanup curl stuff
 qcurl_easy_cleanup(easy_handle);

 /*
  Now chunk.memory points to a memory block that is chunk.size
  bytes big and contains the remote file.

  Nothing has yet deallocated that data, hence free() is used at the end.
 */

 if (!chunk.size) {
  pthread_mutex_lock( &GoogleMessage_mutex );
   sprintf(GoogleMessage.message, "Translation: no data received from Google\n");
   GoogleMessage.new_message = qtrue;
  pthread_mutex_unlock( &GoogleMessage_mutex );
  // Free up memory (same with the end)
  if(chunk.memory) free(chunk.memory);
  free(encoded); 
  free(input);
  return 0;
 }

 if ( ( pos1 = strstr(chunk.memory, "\"translatedText\":\"") ) ) {  // Make sure we use a valid file:

  pos2 = strstr(pos1 + const_strlen, "\""); // position translated text ends

  // Build the translated text:
  final[0] = '\0';
  strncat(final, pos1 + const_strlen, strlen(pos1) - ( strlen(pos2) + const_strlen ) );

  // Final printing of the translated text:
  pthread_mutex_lock( &GoogleMessage_mutex );
   sprintf(GoogleMessage.message, "^2Translated^7: ^3%s\n", final);
   GoogleMessage.new_message = qtrue;
  pthread_mutex_unlock( &GoogleMessage_mutex );    
  #ifdef BUILD_FREETYPE
   TTF_Find_Slot(final, clu.TTF_MessageMaxTime->integer); 
  #endif

 } else {
  pthread_mutex_lock( &GoogleMessage_mutex );
   sprintf(GoogleMessage.message, "Translation: no valid translation file received from Google\n");
   GoogleMessage.new_message = qtrue;
  pthread_mutex_unlock( &GoogleMessage_mutex );  
 }

 // Free allocated memory
 if(chunk.memory) free(chunk.memory);
 free(encoded);
 free(input);
 return 0;
}
EDIT4:假设任何不可见的函数都是线程安全的

static void *Com_GoogleTranslate(void* input) {

 CURL *easy_handle;
 char *pos1, *pos2, url[1024], final[1024], inlang[8], outlang[8], *encoded;
 const int const_strlen = strlen("\"translatedText\":\"");
 struct GoogleMem chunk;

 pthread_mutex_lock( &GoogleMessage_mutex );
  // 'auto' is really empty in google API:
  if (!strcmp(clu.translateIn->string, "auto"))  
   strcpy(inlang, "");
  else            
   strcpy(inlang, clu.translateIn->string);

  if (!strcmp(clu.translateOut->string, "auto")) 
   strcpy(outlang, "");
  else            
   strcpy(outlang, clu.translateOut->string);
 pthread_mutex_unlock( &GoogleMessage_mutex );

 // Build the URL
 url[0] = '\0';
 strcat(url, "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=");

 // Encode input into URL formatting
 encoded = url_encode((char*)input);
 if (!encoded) return 0;

 strcat(url, encoded);
 strcat(url, "&langpair=");
 strcat(url, inlang);
 strcat(url, "|");
 strcat(url, outlang);

 chunk.memory = malloc(1);  // realloc grows it at Com_GoogleTranslateMem()
 if (!chunk.memory) return 0;
 chunk.size = 0;    // no data yet

 // cURL initialization for this sub-session:
 easy_handle = qcurl_easy_init(); 

 // ioq3-urt: was needed on https:// (v2 API) attempts when using GnuTLS
 //qcurl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 3); 

 // set URL:
 qcurl_easy_setopt(easy_handle, CURLOPT_URL, url);

 // ioq3-urt: required for multithreading according to cURL doc.
 qcurl_easy_setopt(easy_handle, CURLOPT_NOSIGNAL, 1);

 // ioq3-urt: skip peer verification; required for google translate when SSL was used
 //qcurl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);

 // send all data to this function
 qcurl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, Com_GoogleTranslateMem);

 // we pass our 'chunk' struct to the callback function:
 qcurl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, (void *)&chunk);

 // some servers don't like requests that are made without a user-agent field, so we provide one:
 qcurl_easy_setopt(easy_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");

 // ioq3-urt: Required by Google Translate terms:
 qcurl_easy_setopt(easy_handle, CURLOPT_REFERER, "ioq3-urt");

 // fetch it
 qcurl_easy_perform(easy_handle);

 // cleanup curl stuff
 qcurl_easy_cleanup(easy_handle);

 /*
  Now chunk.memory points to a memory block that is chunk.size
  bytes big and contains the remote file.

  Nothing has yet deallocated that data, hence free() is used at the end.
 */

 if (!chunk.size) {
  pthread_mutex_lock( &GoogleMessage_mutex );
   sprintf(GoogleMessage.message, "Translation: no data received from Google\n");
   GoogleMessage.new_message = qtrue;
  pthread_mutex_unlock( &GoogleMessage_mutex );
  // Free up memory (same with the end)
  if(chunk.memory) free(chunk.memory);
  free(encoded); 
  free(input);
  return 0;
 }

 if ( ( pos1 = strstr(chunk.memory, "\"translatedText\":\"") ) ) {  // Make sure we use a valid file:

  pos2 = strstr(pos1 + const_strlen, "\""); // position translated text ends

  // Build the translated text:
  final[0] = '\0';
  strncat(final, pos1 + const_strlen, strlen(pos1) - ( strlen(pos2) + const_strlen ) );

  // Final printing of the translated text:
  pthread_mutex_lock( &GoogleMessage_mutex );
   sprintf(GoogleMessage.message, "^2Translated^7: ^3%s\n", final);
   GoogleMessage.new_message = qtrue;
  pthread_mutex_unlock( &GoogleMessage_mutex );    
  #ifdef BUILD_FREETYPE
   TTF_Find_Slot(final, clu.TTF_MessageMaxTime->integer); 
  #endif

 } else {
  pthread_mutex_lock( &GoogleMessage_mutex );
   sprintf(GoogleMessage.message, "Translation: no valid translation file received from Google\n");
   GoogleMessage.new_message = qtrue;
  pthread_mutex_unlock( &GoogleMessage_mutex );  
 }

 // Free allocated memory
 if(chunk.memory) free(chunk.memory);
 free(encoded);
 free(input);
 return 0;
}
我只是在某些系统上出现了不稳定的行为,虽然我怀疑它的硬件有问题(英特尔OpenGL?),但我想知道我是否遗漏了什么

编辑:假设cURL本身是线程安全的


EDIT2:“input”是释放到此线程中的新副本。

只要它在受互斥保护的部分之外调用的所有函数本身都是线程安全的,我就觉得它是线程安全的

static void *Com_GoogleTranslate(void* input) {

 CURL *easy_handle;
 char *pos1, *pos2, url[1024], final[1024], inlang[8], outlang[8], *encoded;
 const int const_strlen = strlen("\"translatedText\":\"");
 struct GoogleMem chunk;

 pthread_mutex_lock( &GoogleMessage_mutex );
  // 'auto' is really empty in google API:
  if (!strcmp(clu.translateIn->string, "auto"))  
   strcpy(inlang, "");
  else            
   strcpy(inlang, clu.translateIn->string);

  if (!strcmp(clu.translateOut->string, "auto")) 
   strcpy(outlang, "");
  else            
   strcpy(outlang, clu.translateOut->string);
 pthread_mutex_unlock( &GoogleMessage_mutex );

 // Build the URL
 url[0] = '\0';
 strcat(url, "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=");

 // Encode input into URL formatting
 encoded = url_encode((char*)input);
 if (!encoded) return 0;

 strcat(url, encoded);
 strcat(url, "&langpair=");
 strcat(url, inlang);
 strcat(url, "|");
 strcat(url, outlang);

 chunk.memory = malloc(1);  // realloc grows it at Com_GoogleTranslateMem()
 if (!chunk.memory) return 0;
 chunk.size = 0;    // no data yet

 // cURL initialization for this sub-session:
 easy_handle = qcurl_easy_init(); 

 // ioq3-urt: was needed on https:// (v2 API) attempts when using GnuTLS
 //qcurl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 3); 

 // set URL:
 qcurl_easy_setopt(easy_handle, CURLOPT_URL, url);

 // ioq3-urt: required for multithreading according to cURL doc.
 qcurl_easy_setopt(easy_handle, CURLOPT_NOSIGNAL, 1);

 // ioq3-urt: skip peer verification; required for google translate when SSL was used
 //qcurl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);

 // send all data to this function
 qcurl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, Com_GoogleTranslateMem);

 // we pass our 'chunk' struct to the callback function:
 qcurl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, (void *)&chunk);

 // some servers don't like requests that are made without a user-agent field, so we provide one:
 qcurl_easy_setopt(easy_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");

 // ioq3-urt: Required by Google Translate terms:
 qcurl_easy_setopt(easy_handle, CURLOPT_REFERER, "ioq3-urt");

 // fetch it
 qcurl_easy_perform(easy_handle);

 // cleanup curl stuff
 qcurl_easy_cleanup(easy_handle);

 /*
  Now chunk.memory points to a memory block that is chunk.size
  bytes big and contains the remote file.

  Nothing has yet deallocated that data, hence free() is used at the end.
 */

 if (!chunk.size) {
  pthread_mutex_lock( &GoogleMessage_mutex );
   sprintf(GoogleMessage.message, "Translation: no data received from Google\n");
   GoogleMessage.new_message = qtrue;
  pthread_mutex_unlock( &GoogleMessage_mutex );
  // Free up memory (same with the end)
  if(chunk.memory) free(chunk.memory);
  free(encoded); 
  free(input);
  return 0;
 }

 if ( ( pos1 = strstr(chunk.memory, "\"translatedText\":\"") ) ) {  // Make sure we use a valid file:

  pos2 = strstr(pos1 + const_strlen, "\""); // position translated text ends

  // Build the translated text:
  final[0] = '\0';
  strncat(final, pos1 + const_strlen, strlen(pos1) - ( strlen(pos2) + const_strlen ) );

  // Final printing of the translated text:
  pthread_mutex_lock( &GoogleMessage_mutex );
   sprintf(GoogleMessage.message, "^2Translated^7: ^3%s\n", final);
   GoogleMessage.new_message = qtrue;
  pthread_mutex_unlock( &GoogleMessage_mutex );    
  #ifdef BUILD_FREETYPE
   TTF_Find_Slot(final, clu.TTF_MessageMaxTime->integer); 
  #endif

 } else {
  pthread_mutex_lock( &GoogleMessage_mutex );
   sprintf(GoogleMessage.message, "Translation: no valid translation file received from Google\n");
   GoogleMessage.new_message = qtrue;
  pthread_mutex_unlock( &GoogleMessage_mutex );  
 }

 // Free allocated memory
 if(chunk.memory) free(chunk.memory);
 free(encoded);
 free(input);
 return 0;
}

然而,有一个关于malloc线程安全性的问题。请参阅。

这不是一个线程安全问题,但有一个突出的潜在问题。以下代码行未检查搜索是否成功:

pos2 = strstr(pos1 + const_strlen, "\""); // position translated text ends
如果
chunk.memory
值在
的“translatedText”:“
值之后不包含另一个双引号,则该值将为null,并且
strncat
中该值的后续
strlen()
可能会导致访问冲突

至少,在那里添加一个
assert
来验证它是否总是成功可能没有什么坏处。但是我不知道其他函数在做什么。如果它们保证字符串中有双引号,那么这就不是问题

此外,从“我对涉及的数据一无所知”的角度来看,问题在于对1024个缓冲区中的字符串长度的盲目假设。从防御性编码的角度来看,对这些调用进行额外检查可能不会有什么坏处


否则,尽管如此,我同意JeremyP(+1)的观点,即基于给定的代码,它看起来是线程安全的。

与Intel和OpenGL有什么联系?它在游戏中运行(在SDL OpenGL上下文中运行)。该函数不直接或间接调用任何OpenGL函数(几乎在任何地方都不安全)然而,英特尔在OpenGL中的名声对OpenGL程序员来说是如此可怕,可怕,可怕,甚至在这方面我也忍不住怀疑。malloc的有趣…使多线程变得更加可怕…那些OpenMP等API毕竟很方便…(自动完成大部分工作)