0

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

缓冲区 = 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:问题是CALOC。当我静态定义 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做错了什么?

4

2 回答 2

0

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

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

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

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

有用。

于 2013-09-21T00:49:12.613 回答
0

好吧,即使这个问题已经很老了,有人可能会像我一样绊倒它,所以我给我 2 美分:如果你在生成之前调用你的缓冲区,你肯定会收到一条消息,但我怀疑它由于一个简单的原因将运行稳定,这将花费您几个小时的研究来理解:即使您保护“共享”缓冲区和缓冲区计数器免受并行访问,您仍然存在一个线程不知道的问题,即另一个线程改变了一些东西。所以它会缓存内存内容(通过软件算法和硬件),并且会看到不再真实的东西。即使您通过滥用“易失性”(用于读取硬件寄存器等)来解决某些问题,并且不会

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

于 2015-04-30T19:05:45.427 回答