问题描述
我是C语言的新手,我认为这里的指针可能存在问题.任何帮助将不胜感激!
I'm new to C, and I think there may be an issue with pointers here. Any help would be appreciated!
我有一个看起来像这样的链表结构:
I have a linkedlist struct that looks like this:
ll.h:
#ifndef LLTEST_LL_H
#define LLTEST_LL_H
#include <stdlib.h>
typedef struct _listNode {
void *data;
struct _listNode *next;
} listNode;
typedef struct {
int logicalLength;
int elementSize;
listNode *head;
listNode *tail;
} linkedlist;
typedef struct table {
const char* name;
size_t col_count;
size_t length;
} table;
typedef struct db {
const char* name;
size_t table_count;
table** tables;
} db;
void list_append(linkedlist *list, void *element);
void create_list(linkedlist *list, int elementSize);
void create_db(const char* db_name, db** db);
#endif //LLTEST_LL_H
main.c
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include "ll.h"
linkedlist databases_list;
void create_list(linkedlist *list, int elementSize)
{
list->logicalLength = 0;
list->elementSize = elementSize;
list->head = NULL;
list->tail = NULL;
}
void list_append(linkedlist *list, void *element)
{
listNode *node = malloc(sizeof(listNode));
node->data = malloc(list->elementSize);
node->next = NULL;
memcpy(node->data, element, list->elementSize);
if(list->logicalLength == 0) {
list->head = list->tail = node;
} else {
list->tail->next = node;
list->tail = node;
}
list->logicalLength++;
}
listNode* find_database_node(char *name){
listNode *node = databases_list.head;
//bool result = true;
listNode *found_node = NULL;
while(node != NULL) {
db *item = (db *)node->data;
if (strcmp(item->name, name) == 0){
found_node = node;
break;
}
node = node->next;
}
return found_node;
}
void get_db_pool(char *name, db *value){
listNode *node = find_database_node(name);
if(node != NULL){
value = (db *)node->data;
}
else{
value = NULL;
}
}
void set_db_pool(db* value){
list_append(&databases_list, (void *)value);
}
void create_db(const char* db_name, db** db) {
if (*db == NULL) {
*db = malloc(sizeof(db));
}
(*db)->name = db_name;
(*db)->table_count = 0;
(*db)->tables = NULL;
}
int main() {
create_list(&databases_list, sizeof(db *));
char* db_name= "mydb";
db* db1 = NULL;
create_db(db_name, &db1);
set_db_pool(db1); //<--this line
return 0;
}
在我标记为<-此行"的行上,当我检查(db)databases_list.head-> data的名称参数时,我看到的是"\ 222 \ 017"而不是"mydb"期望(例如当我检查db1-> name时).我在做什么错了?
On the line that I have marked "<--this line", when I check (db)databases_list.head->data's name parameter, I see "\222\017" instead of "mydb" as I would expect (such as when I check db1->name). What am I doing wrong?
推荐答案
我已经修改了代码,并进行了一些修改以适应我的某些偏见,因此我的行号可能与您的行号略有不同.当我在 valgrind
下运行它时,我会抱怨:
I've taken the revised code and edited a bit to suit some of my prejudices, so my line numbers are probably slightly different from yours. When I run it under valgrind
, I get a complaint:
==55831== Invalid write of size 8
==55831== at 0x100000EC7: main (ll17.c:78)
==55831== Address 0x100a7c350 is 8 bytes after a block of size 8 alloc'd
==55831== at 0x1000066F1: malloc (vg_replace_malloc.c:303)
==55831== by 0x100000EB9: main (ll17.c:73)
==55831==
==55831== Invalid write of size 8
==55831== at 0x100000ECF: main (ll17.c:78)
==55831== Address 0x100a7c348 is 0 bytes after a block of size 8 alloc'd
==55831== at 0x1000066F1: malloc (vg_replace_malloc.c:303)
==55831== by 0x100000EB9: main (ll17.c:73)
第73行如下所示:
void create_db(const char* db_name, db** db) {
if (*db == NULL) {
*db = malloc(sizeof(db)); // 73
}
这会为指针(严格来说是指向指针的指针)而不是 db
结构分配足够的空间.
This allocates enough space for a pointer (strictly, a pointer to a pointer), not for a db
structure.
- 您应该避免使用与(基本)类型同名的变量,这会混淆除编译器之外的所有人.
您真的需要:
void create_db(const char* db_name, db** db) {
if (*db == NULL) {
*db = malloc(sizeof(**db));
}
进行适当的更改后,代码在 valgrind
下运行正常.根据我的 valgrind
构建,它泄漏了很多,但我最近从 Mac OS X 10.10 Yosemite 升级到 10.11 El Capitan,我不相信我的抑制文件能给我任何有用的信息.它是在 Yosemite 下构建的,我还收到了 valgrind
跟踪的未知 fcntl
调用".
With that change in place, the code runs OK under valgrind
. According to my build of valgrind
, it leaks a lot, but I've recently upgraded from Mac OS X 10.10 Yosemite to 10.11 El Capitan, and I don't trust my suppressions file to give me any useful information. It was built under Yosemite, and I'm also getting 'unknown fcntl
calls' tracked by valgrind
.
这篇关于使用void指针模拟C语言中的通用链表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!