使用UT_hash时HASH_FIND_STR始终返回NULL问题求助
重复账户去重功能异常:HASH_FIND_STR无法找到已存在账户
已通过HASH_ADD_KEYPTR将键指针插入hashmap且生效(打印hashmap全部内容显示正常),但调用HASH_FIND_STR查找对应字符串时,exit_entry始终为NULL,无法找到目标账户。buffer为全局变量,代码如下:
// mutex pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // hash node struct hash_buf_struct { char *account_hash; char *password_hash; char *option_hash; UT_hash_handle hh; }; // hash init struct hash_buf_struct *buffer = NULL; struct hash_buf_struct *s = NULL; // Producer thread func void *producer() { while (1) { char rcvbuf[1500]; memset(rcvbuf, '\0', sizeof(rcvbuf)); recvfrom(sockfd, rcvbuf, sizeof(rcvbuf), 0, (struct sockaddr *)&send_to, (socklen_t *)&send_to_len); regmatch_t matches[4]; if (regexec(®ex, rcvbuf, 4, matches, 0) == 0) { char account[256]; char password[256]; char operation[5]; regmatch_t account_match = matches[1]; regmatch_t password_match = matches[2]; regmatch_t operation_match = matches[3]; snprintf( account, account_match.rm_eo - account_match.rm_so + 1, "%s", rcvbuf + account_match.rm_so); snprintf( password, password_match.rm_eo - password_match.rm_so + 1, "%s", rcvbuf + password_match.rm_so); snprintf(operation, operation_match.rm_eo - operation_match.rm_so + 1, "%s", rcvbuf + operation_match.rm_so); // sendto(sockfd, "Done!\n", 7, 0, (const struct sockaddr *)&send_to, (socklen_t)sizeof(send_to)); s = (struct hash_buf_struct*)calloc(sizeof(struct hash_buf_struct), sizeof(char)); s->option_hash = (char *)calloc(strlen(operation) + 1, sizeof(char)); s->password_hash = (char *)calloc(strlen(password) + 1, sizeof(char)); s->account_hash = (char *)calloc(strlen(account) + 2, sizeof(char)); strcat (s->password_hash, password); strcat (s->option_hash, operation); strcat (s->account_hash, account); struct hash_buf_struct *hash = NULL; printf("---------------print test--------------\n"); for (hash = buffer; hash != NULL; hash = (struct hash_buf_struct *)(hash->hh.next)) printf("account = %s\n",hash->account_hash); printf("\n"); struct hash_buf_struct *exit_entry = (struct hash_buf_struct *)calloc(strlen(account) + 1, sizeof(char)); HASH_FIND_STR(buffer, s->account_hash, exit_entry); // cant work if(exit_entry == NULL) { pthread_mutex_lock(&mutex); HASH_ADD_KEYPTR(hh, buffer, s->account_hash, strlen(account) + 1, s); pthread_mutex_unlock(&mutex); } else { if (strcmp(s->option_hash, exit_entry->option_hash) == 0) printf("Repetitive operation"); else { pthread_mutex_lock(&mutex); HASH_ADD_KEYPTR(hh, buffer, s->account_hash, strlen(account) + 1, s); pthread_mutex_unlock(&mutex); } } } else printf("----------------------------------------------------------\nValid format: %s\n\ Please type like: ACCOUNT PASSWORD OPTION(close|open)\n----------------------------------------------------------\n", rcvbuf); } }
问题根源与修复方案
1. HASH_FIND_STR使用错误
HASH_FIND_STR不需要提前为输出指针分配内存,它会直接将找到的节点地址赋值给传入的指针变量。你当前用calloc给exit_entry分配了无关内存,导致HASH_FIND_STR无法正确覆盖该指针,始终返回你分配的空内存地址。
修复:
将:
struct hash_buf_struct *exit_entry = (struct hash_buf_struct *)calloc(strlen(account) + 1, sizeof(char));
改为:
struct hash_buf_struct *exit_entry = NULL;
2. HASH_ADD_KEYPTR键长度参数不匹配
你插入hash时使用的键长度是strlen(account) + 1,但实际存储的键是s->account_hash,其长度应为strlen(s->account_hash)(或直接用strlen(account),因为snprintf已为account添加终止符)。长度不匹配会导致hash计算错误,无法正确查找。
修复:
将HASH_ADD_KEYPTR中的长度参数改为strlen(s->account_hash):
HASH_ADD_KEYPTR(hh, buffer, s->account_hash, strlen(s->account_hash), s);
3. 遍历hashmap未加锁
遍历hashmap的操作未加互斥锁,在多线程环境下会引发并发访问的未定义行为,可能破坏hash结构或导致打印异常。
修复:
遍历前后添加锁:
printf("---------------print test--------------\n"); pthread_mutex_lock(&mutex); for (hash = buffer; hash != NULL; hash = (struct hash_buf_struct *)(hash->hh.next)) printf("account = %s\n",hash->account_hash); pthread_mutex_unlock(&mutex); printf("\n");
4. 内存泄漏风险
当找到重复账户时,新分配的s节点及其内部的字符串内存未被释放,造成内存泄漏。
修复:
在else分支中添加内存释放逻辑:
} else { if (strcmp(s->option_hash, exit_entry->option_hash) == 0) { printf("Repetitive operation"); // 释放新分配的节点内存 free(s->account_hash); free(s->password_hash); free(s->option_hash); free(s); } else { pthread_mutex_lock(&mutex); HASH_ADD_KEYPTR(hh, buffer, s->account_hash, strlen(s->account_hash), s); pthread_mutex_unlock(&mutex); } }
内容的提问来源于stack exchange,提问作者ColaMan
相关产品推荐
相关产品推荐

