我试图学习如何使用嵌套结构,并且正在做一个" pthread生产者和消费者"比如说。
我已经初始化了这些:
int MAILBOX_SIZE = 10;
typedef struct Message {
int bytes;
void *data;
} Message;
typedef struct Mailbox {
Message *queue;
int in; //place to add next element in buffer
int out; //place to remove next element in buffer
int cnt; //number of elements in buffer
} Mailbox;
void mb_init(Mailbox *sb, int size);
现在我想创建这个初始化函数以便能够访问队列。
我的方法可能是错的,但我在想的是:
void mb_init(Mailbox *sb, int size){
sb->queue=(Message*)malloc(sizeof(Message));
sb->queue->bytes = size;
printf("%i\n", sb->queue->bytes);
}
int mb_put(Mailbox *sb, Message *msg){
//actions of the producer
}
int mb_get(Mailbox *sb, Message *msg){
//actions of the consumer
}
我的主要(伪代码,因为我在主要方面有更多)是这样的:
int main() {
struct Mailbox *myMailbox;
mb_init(myMailbox, MAILBOX_SIZE);
}
我最终得到了一个"分段错误",我知道它来自我的" mb_init"函数,因为我不太清楚如何处理嵌套结构。 如何使用嵌套结构设置来自此init函数的消息大小?
感谢任何帮助..我正在学习C;对不起,如果有些事情不是最有效的"要做的事。
答案 0 :(得分:2)
编译器警告(-Wall
)指出了问题。
test.c:27:12: warning: variable 'myMailbox' is uninitialized when used here [-Wuninitialized]
mb_init(myMailbox, MAILBOX_SIZE);
^~~~~~~~~
1 warning generated.
您在myMailbox中传递并使用它而没有为其分配内存。通常,不要传入指向初始化函数的指针,返回一个。
您也不应该在邮箱中初始化空邮件,只需初始化邮箱即可。让任何人添加消息都会初始化消息并将其传入。
Mailbox *mb_init(int size){
Mailbox *sb = malloc(sizeof(Mailbox));
sb->queue = NULL;
sb->in = 0;
sb->out = 0;
sb->cnt = 0;
return sb;
}
这将我们带到下一个问题:您只在队列中为一条消息分配了空间。并且它不存储指向消息的指针,它必须复制它们并且它们会变得很大。
相反,请使用Message指针数组。
const size_t MAILBOX_SIZE = 10;
typedef struct {
size_t bytes;
void *data;
} Message;
typedef struct {
Message **queue;
size_t in; //place to add next element in buffer
size_t out; //place to remove next element in buffer
size_t cnt; //number of elements in buffer
size_t max_size;
} Mailbox;
Mailbox *mb_init(size_t size){
Mailbox *mb = malloc(sizeof(Mailbox));
mb->queue = malloc(sizeof(Message*) * size);
mb->in = 0;
mb->out = 0;
mb->cnt = 0;
mb->max_size = size;
return mb;
}
void mb_destroy( Mailbox *mb ) {
free(mb->queue);
free(mb);
}
我做了一些其他改动。最明显的是切换到size_t
来存储事物的大小。这可以避免碰到整数限制。
我添加了一个析构函数,你应该总是为你的所有结构编写一个初始化器和析构函数。
邮箱现在存储其最大尺寸。它需要知道这一点,以避免添加太多消息。此版本的更高版本将切换到链接列表或根据需要重新分配队列。
我还确保始终使用typedef
,而不是基础结构类型,并且甚至从结构中删除名称,因此无法直接引用它们。现在只有一种方法可以引用结构,这样更容易阅读。如果对类型进行彻底更改,它还提供更强的封装,例如切换到索引其他存储的整数(不太可能,但你永远不知道)。
答案 1 :(得分:1)
正如我已经说过的,你的问题是通过价值而不是通过参考传递。
有很多方法可以做到这一点。你可以尝试这个
在Main
Mailbox myMailbox; // memory allocated on the stack, life span till the *return*
mb_init(&myMailbox, MAILBOX_SIZE); // pass the address here
// and don't forget to free the queue memory when you are done with it
//Main ends here
/* In your code if you don't return a pointer to the memory allocated here on the heap.
You will not get those changes when the function return from the stack.
It is best practice to return a pointer to the allocated heap memory
before the function returns. */
void mb_init(Mailbox *sb, int size){
......
......
}