【问题标题】:How to create an Array of Protocol Buffer Messages in C如何在 C 中创建协议缓冲区消息数组
【发布时间】:2013-09-21 00:32:07
【问题描述】:

阅读之前:你会看到我用来初始化缓冲区的 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));

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

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);
}

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

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

收到的消息数 = 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 时做错了什么吗?

【问题讨论】:

    标签: c multithreading buffer protocols calloc


    【解决方案1】:

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

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

    因此,没有提供足够的信息来重现您的错误或分析代码。 请写隔离测试,并在这里分享。 或者,您可以直接下载我的线程间队列,然后免费使用:

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

    有效。

    【讨论】:

    • 这不是信号量或互斥量的问题,而是协议缓冲区消息数组的问题。互斥量和信号量都在主函数中使用 pthread_mutex_init(&mutex_name) 和 sem_init(&sem, 0, 0) 进行初始化
    • 明天我会尝试添加一个孤立的测试用例,以便可以重现错误
    【解决方案2】:

    好吧,即使这个问题已经很老了,有人可能会像我一样绊倒它,所以我给我 2 美分: 如果你 calloc() 你的缓冲区在生成之前,你肯定会收到一条消息,但我怀疑它是否会因为一个简单的原因稳定运行,这需要你几个小时的研究才能理解: 即使您保护“共享”缓冲区和缓冲区计数器免受并行访问,您仍然会遇到问题,即一个线程不知道,另一个线程更改了某些内容。所以它会缓存内存内容(通过软件算法和硬件),并且会看到不再真实的东西。 即使您通过滥用“易失性”(用于读取硬件寄存器等并且不会保护完整的类实例)来修复某些问题,您仍然会绊倒编译器优化(指令顺序)以及硬件多流水线等等,这将再次扼杀你的逻辑。

    阅读“记忆障碍”,了解它们,然后您的(新)代码可能会起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      相关资源
      最近更新 更多