0

I'm writing a Client-Server program like database, while debugging there is an error "Syscall param write(buf) points to uninitialised byte(s)":

terminal (valgrind)

add qetqetqe qetqetq 1355135
==28928== Syscall param write(buf) points to uninitialised byte(s)
==28928==    at 0x4BCFA37: write (write.c:26)
==28928==    by 0x10CF73: Client::Handle(bool, bool) (server.cpp:379)
==28928==    by 0x10CEF8: Client::Run() (server.cpp:372)
==28928==    by 0x10A618: main (main_client.cpp:15)
==28928==  Address 0x4de0e8c is 524 bytes inside a block of size 560 alloc'd
==28928==    at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==28928==    by 0x10C7F3: Client::Connect(char const*, int) (server.cpp:267)
==28928==    by 0x10A5EB: main (main_client.cpp:8)
==28928==  Uninitialised value was created by a heap allocation
==28928==    at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==28928==    by 0x10C7F3: Client::Connect(char const*, int) (server.cpp:267)
==28928==    by 0x10A5EB: main (main_client.cpp:8)
==28928== 

I sent fragments of code in which it may be an error and described structures and classes:

server.hpp

#ifndef SERVER_SENTER
#define SERVER_SENTER

#include "psdatabase.hpp"

enum
{
    current_max_lcount = 16,
    buffsize = 1024,
};

enum command_stat            // for command handling
{
    add_comm = 1,
    edit_comm,
    remove_comm,
    get_comm,
    quit_comm,
    success,
    not_found = -2,
    uninitialized
};

struct message_struct        // that structure I'll sent via Internet to server
{
    DbObject dbobj;
    _pesel_len sel_pesel;
    command_stat command;
    message_struct()
        : dbobj(),
          sel_pesel(0), command(uninitialized) {}
    ~message_struct() {}
    void Clear();
};

class FdHandler
{
    int fd;
    bool want_read;
    bool want_write;

public:
    FdHandler(int _fd) : fd(_fd), want_read(true), want_write(false) {}
    virtual ~FdHandler();

    int GetFd() { return fd; }

    void SetRead(bool _want_read) { want_read = _want_read; }
    void SetWrite(bool _want_write) { want_write = _want_write; }

    bool WantRead() { return want_read; }
    bool WantWrite() { return want_write; }

    virtual void Handle(bool r, bool w) = 0;
};
...
class Client : FdHandler
{
    message_struct buf;
    bool quit_flag;

    Client(int _fd) : FdHandler(_fd), quit_flag(true)
    {
        buf.Clear();
    }

public:
    virtual ~Client() {}
    static Client *Connect(const char *ip, int port);
    void Run();

private:
    virtual void Handle(bool r, bool w);
};

#endif

psdatabase.hpp

#ifndef PSDATABASE_SENTER
#define PSDATABASE_SENTER

#include <string.h>

#define ID_FILE_NAME "ID/ID_MAX.bin"                       // the path to file
                                                           // where the last
                                                           // id saves
#define TEXT_DATABASE_NAME "PERSON_DAT/PERSON.dat"         // the path to
                                                           // database
#define TEXT_DATABASE_NAME_NEW "PERSON_DAT/PERSON_NEW.dat" // the path to new
                                                           // database for
                                                           // shifting database

#define PRINT_FORMAT "%40lld %50s %50s %40lld\n"     // format for
                                                     // showing all
                                                     // database
#define WRITING_FORMAT "%40lld %250s %250s %40lld\n" // format for writing to
                                                     // database, reading from
                                                     // database

enum
{
    writing_format_len = 584,
    buffer_size = 250,
    max_person_in_dynamic_array = 50
};

typedef long long _id_len;             // variable for id
typedef unsigned long long _pesel_len; // variable for PESEL
typedef char _byte;                    // variable for byte
typedef long _position;                // variable for position in file
...
struct DbObject                // that object I'll write to pseudo database
{                              // I cannot tell it a database, so I call it pseudo database
    _id_len id;
    char name[buffer_size];
    char surname[buffer_size];
    _pesel_len pesel;                  // PESEL is a Polish Resident Identification Number

    DbObject() : id(-1), pesel(0)
    {
        bzero(name, buffer_size);
        bzero(surname, buffer_size);
    }
    DbObject(_id_len _id, const char *_name,
             const char *_surname, _pesel_len _pesel) : id(_id), pesel(_pesel)
    {
        strcpy(name, _name);
        strcpy(surname, _surname);
    }
};
...
#endif

server.cpp

#include <unistd.h>
#include <sys/select.h>
#include <errno.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include "server.hpp"
...
Client *Client::Connect(const char *ip, int port) // if connection is successful create 
{                                                 // a dynamic client object
    int _fd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == _fd)
        return 0;

    int opt = 1;
    setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in addr_client;
    addr_client.sin_addr.s_addr = inet_addr("127.0.0.135");
    addr_client.sin_port = htons(port);
    addr_client.sin_family = AF_INET;

    if (-1 == bind(_fd, (struct sockaddr *)&addr_client, sizeof(addr_client)))
        return 0;

    struct sockaddr_in addr_server;
    addr_server.sin_port = htons(port);
    addr_server.sin_family = AF_INET;
    addr_server.sin_addr.s_addr = inet_addr(ip);

    int stat =
        connect(_fd, (struct sockaddr *)&addr_server, sizeof(addr_server));

    if (stat == -1)
        return 0;

    return new Client(_fd);                          // line 267
}

void Client::Run()                                   // run a client
{
    while (quit_flag)
    {
        char buf_command[10];                        // create buffer fields for 
        char buf_pesel[40];                          // future handling and conversion
        char buf_sel_pesel[40];
        fd_set rds, wrs;
        FD_ZERO(&rds);
        FD_ZERO(&wrs);

        scanf("%s", buf_command);                    // read from a standard input stream

        if (!strcmp(buf_command, "add"))             // handle string which should
            buf.command = add_comm;                  // be a command
        else if (!strcmp(buf_command, "edit"))
            buf.command = edit_comm;
        else if (!strcmp(buf_command, "remove"))
            buf.command = remove_comm;
        else if (!strcmp(buf_command, "quit"))
            buf.command = quit_comm;
        else
        {
            printf("Unknown command...\n");
            continue;
        }

        switch (buf.command)                         // handle a command
        {
        case add_comm:
            scanf("%s %s %s", buf.dbobj.name, buf.dbobj.surname,
                  buf_pesel);
            buf.dbobj.id = 0;
            buf.dbobj.pesel = atoll(buf_pesel);      // convert string written pesel to 
            if (!buf.dbobj.pesel)                    // unsigned long long (_pesel_len)
            {                                        // (see typedefs in psdatabase.hpp)
                printf("Usage: add <name> <surname> <pesel>\n");
                continue;
            }
            SetWrite(true);                          // we are going to write a data
            SetRead(false);                          // to server and not read from server
            break;                                   // so set readflag false,
        case edit_comm:                              // writeflag true
            scanf("%s %s %s %s", buf_sel_pesel, buf.dbobj.name,
                  buf.dbobj.surname, buf_pesel);
            buf.dbobj.id = 0;
            buf.dbobj.pesel = atoll(buf_pesel);
            buf.sel_pesel = atoll(buf_sel_pesel);
            if (!buf.dbobj.pesel || !buf.sel_pesel)
            {
                printf("Usage: edit <sel_pesel> <name> <surname> <pesel>\n");
                continue;
            }
            SetWrite(true);
            SetRead(false);
            break;
        case get_comm:
            scanf("%s", buf_sel_pesel);
            buf.dbobj.id = 0;
            buf.sel_pesel = atoll(buf_sel_pesel);
            if (!buf.sel_pesel)
            {
                printf("Usage: get <sel_pesel>\n");
                continue;
            }
            SetWrite(true);
            SetRead(true);
            break;
        case remove_comm:
            scanf("%s", buf_sel_pesel);
            buf.dbobj.id = 0;
            buf.sel_pesel = atoll(buf_sel_pesel);
            if (!buf.sel_pesel)
            {
                printf("Usage: remove <sel_pesel>\n");
                continue;
            }
            SetWrite(true);
            SetRead(false);
            break;
        default:
            continue;
            break;
        }

        if (WantWrite())                      // if our client want to read from server
            FD_SET(GetFd(), &wrs);            // or write to, set client descriptor
        if (WantRead())                       // to readset and writeset
            FD_SET(GetFd(), &rds);

        int stat = select(GetFd() + 1, &rds, &wrs, 0, 0);

        if (stat <= 0)
        {
            quit_flag = false;
            continue;
        }

        bool r = FD_ISSET(GetFd(), &rds);
        bool w = FD_ISSET(GetFd(), &wrs);

        if (r || w)                          // handle an event
            Handle(r, w);                            // line 372
    }
}

void Client::Handle(bool r, bool w)
{
    if (w)
        write(GetFd(), &buf, sizeof(buf));           // line 379
    if (r)
    {
        buf.Clear();                         // update our buffer
        int rc = read(GetFd(), &buf, sizeof(buf));
        if (rc <= 0)
        {
            quit_flag = false;
            return;
        }
        switch (buf.command)
        {
        case success:
            printf("Success!\n");
            break;
        case not_found:
            printf("Not found...\n");
            break;
        default:
            break;
        }
    }
}

main_client.cpp

#include <stdio.h>
#include "server.hpp"

static int port = 8898;

int main()
{
    Client *cl = Client::Connect("127.0.0.35", port);
    if (!cl)
    {
        perror("Error");
        return 1;
    }

    cl->Run();
    return 0;
}

Now I'm writing static IP address for client and server and in the future i correct it.

tell me please what should I do or where is it uninitialized bytes.

If you need all the code, please let me know. I published a part of my code in which it may be an error and another fragment for better understanding of described classes and etc.

Thank you for attention!

Barmar
  • 741,623
  • 53
  • 500
  • 612
CH_YUR
  • 25
  • 6
  • 2
    I don't think you can write a non-POD structure to the network. – Barmar Jun 15 '22 at 21:27
  • @Barmar I read about this on the Internet, do I understand correctly that a POD structure is a structure that consists exclusively of fields and does not contain methods? If yes, then to fix this error, I need to remove all constructors, methods from my structures, and can I already process them from other classes / structures in which I inherit the structure that I send over the network? – CH_YUR Jun 15 '22 at 21:48
  • 1
    That's close.. See https://stackoverflow.com/questions/146452/what-are-pod-types-in-c for a more detailed definition. – Barmar Jun 15 '22 at 21:49
  • 1
    The simplest way to think of it is a struct that you could implement in C, without C++ features. – Barmar Jun 15 '22 at 21:50
  • 1
    You should not use `struct`s as network protocols. You are subject to nearly a dozen causes of variation in layout at both end. You need to design an application protocol defined in octets, and write a little library to send and receive it. – user207421 Jun 16 '22 at 00:50

0 Answers0