使用malloc分配缓冲区时客户端服务器应用程序中的问题

5us2dqdw  于 2023-01-20  发布在  其他
关注(0)|答案(4)|浏览(166)

我正在做一个包含服务器-客户端通信的项目。我们的代码不是一直都能工作,有时候它能完美地工作。但是有时候我们要么超时,要么我们的缓冲区不能正常工作。这就是为什么我们想要实现malloc()。你认为这会有帮助吗?我们在malloc()之前的代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>

#define BUFFERSIZE 1024                                              
#define VERSION "VERSION 3.4\n"

#include "functions.h"

char buffer[BUFFERSIZE];

void resetBuffer(char *buffer) {
    memset((buffer), '\0', strlen(buffer));
}

void receiveAnswer(int sock) {
    resetBuffer(buffer);
    size_t length;
    bool x = true;

    while (x) {
        recv(sock, buffer, sizeof(buffer), 0);
        length = strlen(buffer);
        if (buffer[length-1]  == '\n') {
            x = false;
        }
    }

    if (buffer[0] == '-') {
        printf("Error: %s", buffer);
    } else {
        printf("%s\n ", buffer);
    }
}

void sendResponse(int sock, char *message) {
    resetBuffer(buffer);
    strcpy(buffer, message);

    bool x = true;
    size_t length;

    while(x) {
        send(sock, buffer, strlen(buffer), 0);
        length = strlen(buffer);
        if (buffer[length - 1] == '\n') {
            x = false;
        }
    }

    printf("Client: %s\n", buffer);
}

int performConnection(int sock, char *gameID) {
    receiveAnswer(sock);
    sleep(1);
    receiveAnswer(sock);
    sleep(1);
    sendResponse(sock, VERSION);
    sleep(1);
    receiveAnswer(sock);
    sleep(1);
    sendResponse(sock, gameID);
    sleep(1);
    receiveAnswer(sock);
    sleep(1);
    sendResponse(sock, "PLAYER \n");
    sleep(1);
    receiveAnswer(sock);

    resetBuffer(buffer);

    return 0;
}

我们的malloc()代码根本不起作用:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>

#define BUFFERSIZE 1024
#define VERSION "VERSION 3.4\n"

#include "functions.h"

char *buffer;

void resetBuffer(char *buffer) {
    memset((buffer), '\0', strlen(buffer));
}

void receiveAnswer(int sock) {
    resetBuffer(buffer);
    size_t length;
    bool x = true;

    while (x) {
        recv(sock, buffer, sizeof(buffer), 0);
        length = strlen(buffer);
        if (buffer[length-1] == '\n') {
            x = false;
        }
    }

    if (buffer[0] == '-') {
        printf("Error: %s", buffer);
    } else {
        printf("%s\n ", buffer);
    }
}

void sendResponse(int sock, char *message) {
    resetBuffer(buffer);
    strcpy(buffer, message);

    bool x = true;
    size_t length;

    while (x) {
        send(sock, buffer, strlen(buffer), 0);
        length = strlen(buffer);
        if (buffer[length - 1] == '\n') {
            x = false;
        }
    }

    printf("Client: %s\n", buffer);
}

int performConnection(int sock, char *gameID) {
    buffer = (char *)malloc(sizeof(char) * BUFFERSIZE);
    receiveAnswer(sock);
    sleep(1);
    receiveAnswer(sock);
    sleep(1);
    sendResponse(sock, VERSION);
    sleep(1);
    receiveAnswer(sock);
    sleep(1);
    sendResponse(sock, gameID);
    sleep(1);
    receiveAnswer(sock);
    sleep(1);
    sendResponse(sock, "PLAYER \n");
    sleep(1);
    receiveAnswer(sock);

    resetBuffer(buffer);
    free(buffer);
    return 0;
}

任何帮助,不胜感激!Best Enno

8ftvxx2r

8ftvxx2r1#

resetBuffer(buffer);在未初始化的数据上尝试strlen(buffer)时失败。这会调用 * undefined behavior *(UB),因为strlen()需要指向 * string * 的指针。
相反:

// resetBuffer(buffer);
memset(buffer, 0, sizeof(char)* BUFFERSIZE);
// or simply
memset(buffer, 0, BUFFERSIZE);
rnmwe5a2

rnmwe5a22#

这个

void resetBuffer(char* buffer){
   memset((buffer), '\0', strlen(buffer));
}

是未定义的行为。它取决于缓冲区以前的内容(strlen查找0终止符)
你需要传入一个长度(不是从strlen得到的)

k5hmc34c

k5hmc34c3#

为什么要为reset_buffer()函数费心呢?
每次调用都出现在strcpy()之前,后者并不关心缓冲区是否被"重置"(希望缓冲区足够大,可以容纳要放入其中的内容)。
最后一个调用出现在free()之前,同样,缓冲区的内容是无关紧要的。
更令人担心的是buffer[]已经变成了*buffer ... receive函数中的sizeof(buffer)现在告诉recv有8个字节(您的机器上的指针大小)需要填充,而不是"pre-malloc"版本的1024个字节。
变更:

void receiveAnswer (int sock){
// ...
        recv(sock, buffer, sizeof(buffer), 0);

recv(sock, buffer, BUFFERSIZE, 0);

这不是一个MRE,所以这个"修复"虽然正确,但可能不是完整的解决方案。

vwhgwdsa

vwhgwdsa4#

buffer不一定包含正确的C字符串,因此使用strlen计算接收的字节数是不正确的:使用recv的返回值。类似地,缓冲区清除函数应该获取长度作为参数或使用BUFFER_SIZE
无论buffer是定义为全局字节数组还是在使用前从堆中分配,都没有关系,您的代码与malloc函数的 * 实现 * 无关。

相关问题