pthread_join后释放资源报错
写了两段代码,第一段是man pthread_join的例子,可正常释放pthread_join返回的res,另一段代码类似,不过在释放由pthread_join返回的指针free(res)时出现的堆多次释放的问题,不知为何,代码如下:
运行正常代码(可通过man pthread_join看到或者见附件):
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct thread_info { /* Used as argument to thread_start() */
pthread_t thread_id; /* ID returned by pthread_create() */
int thread_num; /* Application-defined thread # */
char *argv_string; /* From command-line argument */
};
/* Thread start function: display address near top of our stack,
and return upper-cased copy of argv_string */
static void *
thread_start(void *arg)
{
struct thread_info *tinfo = (struct thread_info *) arg;
char *uargv, *p;
printf("Thread %d: top of stack near %p; argv_string=%s\n",
tinfo->thread_num, &p, tinfo->argv_string);
uargv = strdup(tinfo->argv_string);
if (uargv == NULL)
handle_error("strdup");
for (p = uargv; *p != '\0'; p++)
*p = toupper(*p);
return uargv;
}
int
main(int argc, char *argv[])
{
int s, tnum, opt, num_threads;
struct thread_info *tinfo;
pthread_attr_t attr;
int stack_size;
void *res;
/* The "-s" option specifies a stack size for our threads */
stack_size = -1;
while ((opt = getopt(argc, argv, "s:")) != -1) {
switch (opt) {
case 's':
printf("optarg: %s\n", optarg);
stack_size = strtoul(optarg, NULL, 0);
break;
default:
fprintf(stderr, "Usage: %s [-s stack-size] arg ... \n", argv);
exit(EXIT_FAILURE);
}
}
num_threads = argc - optind;
/* Initialize thread creation attributes */
s = pthread_attr_init(&attr);
if (s != 0)
handle_error_en(s, "pthread_attr_init");
if (stack_size > 0) {
s = pthread_attr_setstacksize(&attr, stack_size);
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize");
}
/* Allocate memory for pthread_create() arguments */
tinfo = calloc(num_threads, sizeof(struct thread_info));
if (tinfo == NULL)
handle_error("calloc");
/* Create one thead for each command-line argument */
for (tnum = 0; tnum < num_threads; tnum++) {
tinfo.thread_num = tnum + 1;
tinfo.argv_string = argv;
/* The pthread_create() call stores the thread ID into corresponding element of tinfo[] */
s = pthread_create(&tinfo.thread_id, &attr,
&thread_start, &tinfo);
if (0 != s)
handle_error_en(s, "pthread_create");
}
/* Destroy the thread attributes object, since it is no longer needed */
s = pthread_attr_destroy(&attr);
if (0 != s)
handle_error_en(s, "pthread_attr_destroy");
/* Now join with each thread, and display its returned value */
for (tnum = 0; tnum < num_threads; tnum++) {
s = pthread_join(tinfo.thread_id, &res);
if (0 != s)
handle_error_en(s, "pthread_join");
printf("Joined with thread %d; returned value was %s\n",
tinfo.thread_num, (char *) res);
free(res); /* Free memory allocated by thread */
}
free(tinfo);
exit(EXIT_SUCCESS);
}
运行异常代码(可下载附件源码):
/*
* used syscall:
* pthread_key_create;
* pthread_once;
* pthread_getspecific;
* pthread_setspecific;
*/
#include <limits.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#define ARG_MAX 1000
#define THREADS_NUM 1
#define THREAD_STACK_SIZE 0x100000
#define handle_error_en(en, msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
static pthread_key_t key;
static pthread_once_t init_done = PTHREAD_ONCE_INIT;
pthread_mutex_t env_mutex = PTHREAD_MUTEX_INITIALIZER;
extern char **environ;
struct thread_info {
pthread_t thread_id;
int thread_num;
char *argv_string;
};
static void
thread_init(void)
{
pthread_key_create(&key, free);
}
char *
getenv(const char *name)
{
int i, len;
char *envbuf;
pthread_once(&init_done, thread_init);
pthread_mutex_lock(&env_mutex);
envbuf = (char *)pthread_getspecific(key);
if (NULL == envbuf) {
envbuf = malloc(ARG_MAX);
if (NULL == envbuf) {
pthread_mutex_unlock(&env_mutex);
return (NULL);
}
pthread_setspecific(key, envbuf);
}
len = strlen(name);
for (i = 0; environ != NULL; i++) {
if ((strncmp(name, environ, len) == 0) &&
(environ == '=')) {
strcpy(envbuf, &environ);
pthread_mutex_unlock(&env_mutex);
return (envbuf);
}
}
pthread_mutex_unlock(&env_mutex);
return (NULL);
}
void *
fn(void *arg)
{
return getenv((const char *)arg);
}
int
main(int argc, char *argv[])
{
int tnum, err;
pthread_t tid;
struct thread_info *tinfo;
void *res;
pthread_attr_t attr;
char name[] = "PATH";
err = pthread_attr_init(&attr);
if (0 != err)
handle_error_en(err, "pthread_attr_init");
if (THREAD_STACK_SIZE > 0) {
err = pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
if (0 != err)
handle_error_en(err, "pthread_attr_setstacksize");
}
tinfo = calloc(THREADS_NUM, sizeof(struct thread_info));
if (NULL == tinfo)
handle_error("calloc");
for (tnum = 0; tnum < THREADS_NUM; tnum++)
{
tinfo.thread_num = tnum + 1;
tinfo.argv_string = "test";
err = pthread_create(&tinfo.thread_id, &attr,
fn, (void *)name);
if ( 0 != err)
handle_error_en(err, "pthread_create");
}
err = pthread_attr_destroy(&attr);
if (0 != err)
handle_error_en(err, "pthread_attr_destroy");
for (tnum = 0; tnum < THREADS_NUM; tnum++) {
err = pthread_join(tinfo.thread_id, &res);
if (0 != err)
handle_error_en(s, "pthread_join");
printf("Joined with thread %d; returned value was %s\n",
tinfo.thread_num, (char *) res);
free(res);
}
free(tinfo);
exit(EXIT_SUCCESS);
}
自己顶一个 自已再顶一个,希望有好心人解答! 还是没人回啊 本帖最后由 井蛙夏虫 于 2013-06-04 12:27 编辑
回复 4# lizhenneng
对于pthread_key_create:An optional destructor function may be associated with each key value.At thread exit, if a key value has a non-NULL destructor pointer, and the thread has a non-NULL valueassociatedwiththat key,the value of the key is set to NULL, and then the function pointed to is called with the previously associated value as its sole argument.所以在你调用pthread_join后,线程局部存储已经被释放,你不应当再次调用free来释放。pthread_join后的printf引用指向线程局部存储的res变量也是不合法的。
你可以将pthread_key_create调用的free参数换为NULL试试。
页:
[1]