代码 - 主循环:
int handleClient (struct clientData* clientData)
{
void* Buffer = malloc (INET_BUFFER_SIZE); <-- VOID* BUFFER FOR RECV()
int listenSocket = clientData->listenSocket;
struct sockaddr_in clientAddress = clientData->clientAddress;
printf("Received connection from client %s:%d.\n", inet_ntoa(clientAddress.sin_addr), ntohs(clientAddress.sin_port));
while (1)
{
int packetSize;
if ((packetSize = recv(listenSocket, &Buffer, INET_BUFFER_SIZE, 0)) > 0)
{
if (packetSize == ECHO_SIZE)
{
handleEchoPacket(Buffer);
continue;
}
if (packetSize == MESSAGE_SIZE) <---THIS IS TRIGGERED BECAUSE OF PACKET SIZE
{
handleMessagePacket(Buffer);
continue;
}
}
}
代码 - handleMessagePacket(void * Buffer):
void handleMessagePacket (void* Buffer)
{
void* localBuffer = (void*) malloc(INET_BUFFER_SIZE);
memcpy(localBuffer, Buffer, INET_BUFFER_SIZE); <--SEGFAULT
(...)
}
GDB - 部分输出:
Program received signal SIGSEGV, Segmentation fault.
__memcpy_sse2_unaligned () (.....) <--Tells me it doesn't have source files, not relevant to the problem.
基本上,当我将一个内存块从void指针复制到本地缓冲区时,就会出现问题。两者都是相同类型的malloc()堆内存:void。 欢迎任何建议或意见!
答案 0 :(得分:1)
以下是正在发生的事情:当您将Buffer
的地址传递给recv
时,接收的数据将被放置在分配给缓冲区地址的空间中,该地址位于堆栈中。当您随后致电handleMessagePacket
时,您传递的地址不再有效:已由recv
覆盖!
从recv
的调用中删除&符应该可以解决此问题:
if ((packetSize = recv(listenSocket, Buffer, INET_BUFFER_SIZE, 0)) > 0)
// ^^ No ampersand
通常,像这样的情况最好用内存分析器诊断,例如valgrind。该工具会立即告诉您写入Buffer
写入的堆栈区域无效,并且后续取消引用接收数据作为指针(现在导致SIGSEGV的问题)是无效读取。