如何在C中创建协议缓冲区消息数组

时间:2013-09-21 00:32:07

标签: c multithreading buffer protocols calloc

在您阅读之前:您将看到我用来初始化缓冲区的calloc是导致问题的原因,但我仍然不知道为什么。静态定义缓冲区数组可以解决问题,因为您将看到是否继续阅读......

我正在编写一个由2个线程组成的UDP服务器:一个接收和解析线程。接收线程使用recvfrom监听套接字,并将收到的消息推送到received_msgs_buf数组。解析线程从received_msgs_buf数组中弹出,并决定如何处理它。

received_msgs_buf数组受互斥锁保护,信号量通知解析消息线程尝试从数组中弹出消息。问题是,每当我尝试将收到的消息推送到received_msgs_buf时,我都会遇到段错误。

以下是我为缓冲区分配内存的方法:

// this is in the header file
extern UXIMessage::Wrapper* received_msgs_buf;

// this is in the main.cpp file that calls pthread_create()
UXIMessage::Wrapper* received_msgs_buf;

// This is in the init function for the receive thread, defined in the udp.cpp file
received_msgs_buf = (UXIMessage::Wrapper*)calloc(MAX_NUM_MSGS_IN_QUEUE, sizeof(UXIMessage::Wrapper));

这是我在接收线程中调用的push函数:

void push_to_receive_buf(UXIMessage::Wrapper uxi_msg) {
  pthread_mutex_lock(&received_msgs_mutex);
  if( num_received_msgs < MAX_NUM_MSGS_IN_QUEUE ) {
    printf("Message to put in buffer = %s\n", uxi_msg.DebugString().c_str());
    printf("Num received messages = %d\n", num_received_msgs);
    printf("Buf = %d\n", received_msgs_buf);
            // THE FOLLOWING LINE SEGFAULTS
    received_msgs_buf[num_received_msgs++] = uxi_msg;
  }
  pthread_mutex_unlock(&received_msgs_mutex);
  sem_post(&received_msgs_sem);
}

从print语句中我可以看到接收到的消息数正确初始化为0,接收的消息完全有效,缓冲区指针不为NULL。这是打印输出:

放入缓冲区的消息= message_id:OCU_HEARTBEAT ocu_heartbeat {   ocu_id:4747 }

Num收到消息= 0

Buf = 778112

段错误发生在CopyFrom()函数中,这是由=运算符调用的。

编辑:已经很晚了,但我明天会尝试使用C ++ std :: vector ...

Edit2:为了澄清,互斥体和信号量都在主函数中正确初始化,如下所示:

pthread_mutex_init(&received_msgs_mutex);
pthread_mutex_init(&msgs_to_send_mutex);
sem_init(&received_msgs_sem, 0, 0);
sem_init(&msgs_to_send, 0, 0);

EDIT3:问题是CALLOC。当我静态定义received_msgs_buf时,如下所示:

 // this is in the header file
extern UXIMessage::Wrapper received_msgs_buf[MAX_NUM_MSGS_IN_BUF];

// this is in the main.cpp file that calls pthread_create()
UXIMessage::Wrapper received_msgs_buf[MAX_NUM_MSGS_IN_BUF];

代码有效......有没有人知道我在使用calloc做错了什么?

2 个答案:

答案 0 :(得分:0)

首先,我没有看到你的互斥变量的初始化receive_msgs_mutex - 也不是静态的,也不是pthread_mutex_init()。所以,也许初始值是错误的。

其次,你用信号量做某事...... 此外,没有关于初始化的信息,或锁定它。

因此,没有提供足够的信息来重现您的错误或分析代码。 请写隔离测试,并在此处分享。 或者,您可以只下载我的interthread队列,并免费使用它:

http://olegh.cc.st/Queue.cpp.txt

有效。

答案 1 :(得分:0)

好吧,即使这个问题很老,有人可能会像我一样偶然发现它,所以我给出了2美分: 如果你在生成之前调用了你的缓冲区,你肯定会收到一条消息,但我怀疑它会因为一个简单的原因而运行稳定,这需要你花几个小时的研究来理解: 即使你保护你的共享&#34;来自并行访问的缓冲区和缓冲区计数器,你仍有问题,一个线程不知道,另一个线程改变了什么。因此它将CACHE内存内容(通过软件算法以及硬件)并且将会看到不再是真实的内容。 即使你通过滥用&#34; volatile&#34;来解决一些问题。 (它用于读取硬件寄存器等,并且不会保护完整的类实例),您仍然会偶然发现编译器优化(指令排序)以及硬件多流水线等,这将再次扼杀您的逻辑。

了解&#34;内存障碍&#34;,了解它们,然后您的(新)代码可能会有效。