Home > other >  String inside struct become weird symbols after passing to a method
String inside struct become weird symbols after passing to a method

Time:12-27

I have a struct named task it's a linked list, it contain a struct timing and a command, it's used to store the command i have to execute at a certain time

// and here is the struct command:
struct argument {
    size_t length; // length of the data string
    char *data;
};
typedef struct argument argument;

struct command {
    int argc; // amount of arguments(words) in argv
    argument *argv; // here i already tried put argument **argv
};
typedef struct command command;

I initialize the task with task *this_task = malloc(sizeof(task)); and initialize the command with command *cmds = malloc(sizeof(command)), I add the commands with this méthod:

command *addToCommand(command *cmd, size_t argSize, char *arg) {
    argument *currentArgument = malloc(sizeof(argument)   argSize * sizeof(char));
    if (currentArgument == NULL) {
        cmd = NULL;
        return cmd;
    }
    currentArgument->length = argSize;
    currentArgument->data = arg;

    if (cmd == NULL) {
        cmd = malloc(sizeof(command));
        if (cmd == NULL) return cmd;
        cmd->argv = malloc(sizeof(argument));
        cmd->argv[0] = *currentArgument;
        cmd->argc = 1;
    } else {
        cmd->argc  ;
        cmd->argv = realloc(cmd->argv, (cmd->argc) * sizeof(argument));
        cmd->argv[cmd->argc-1] = *currentArgument;
    }
    return cmd;
}

and then set it with this_task->cmd = cmds;

Now the problem, just after i did all this i printed the first argv of my task with printf( "%s\n", this_task->cmd->argv[0].data), and it show 'test-0' how it should. but the moment when i send it to an another method, like addTask(this_task), and print it again on the first line of the addTask method it show weird symbols like "p<a�". For example for this code :

void addTask(task *task_to_add) {
    printf("arg inside addTask = '%s'\n", task_to_add->cmd->argv[0].data);
   // i'm doing things here but even when everything is commented the bug happen 
}

printf("arg before addTask = '%s'\n", this_task->cmd->argv[0].data);
addTask(this_task);
printf("arg after addTask = '%s'\n", this_task->cmd->argv[0].data);

it show

arg before addTask = 'test-0'
arg inside addTask = '`��'
arg after addTask = '`��'

Since i have no idea where the issue may be and the post seem already a bit long, tell me if you need more code

EDIT: In this project i'm writing the command to a pipe, and reading it in the code above. And while trying to make a minimal reproducible example i noticed that when i remove the part reading from pipes and directly force the value for "test-0", it's not bugging anymore, so does the problem happen from how i'm reading the pipes? I also tried the solution of the "possible duplicate" but didn't worked and as i said, the issue is probably from how i read the pipe I also noticed that if i don't have any other printf before the one displaying "arg before addTask ...",, the arg before show " ", i commented it and wrote "THIS PRINTF" near it

How I compile and run:

gcc src/saturnd.c -o saturnd
gcc src/cassini.c  -o cassini
./saturnd
./cassini (in another terminal)

The code who's reading the pipe:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <endian.h>

struct argument {
    size_t length;
    char *data;
};
typedef struct argument argument;

struct command {
    int argc;
    argument *argv;
};
typedef struct command command;

struct task {
    int id;
    struct timing *timing;
    command *cmd;
    struct task *next;
};
typedef struct task task;


struct timing {
    uint64_t minutes;
    uint32_t hours;
    uint8_t daysofweek;
};


int readHere;
task *tasks = NULL;

command *addToCommand(command *cmd, size_t argSize, char *arg) {
//    printf("adding to cmd %s\n", arg);
    argument *currentArgument = malloc(sizeof(argument)   argSize * sizeof(char));
    if (currentArgument == NULL) {
        cmd = NULL;
        return cmd;
    }
    currentArgument->length = argSize;
    currentArgument->data = arg;

    if (cmd == NULL) {
        cmd = malloc(sizeof(command));
        if (cmd == NULL) return cmd;
        cmd->argv = malloc(sizeof(argument));
        cmd->argv[0] = *currentArgument;
        cmd->argc = 1;
    } else {
        cmd->argc  ;
        cmd->argv = realloc(cmd->argv, (cmd->argc) * sizeof(argument));
        cmd->argv[cmd->argc - 1] = *currentArgument;
    }
    return cmd;
}

void addTask(task *task_to_add) {
    printf("arg inside addTask = '%s'\n", task_to_add->cmd->argv[0].data);
}

int main() {
    char *readHere_path = "saturndReadPipe";
    mkfifo(readHere_path, S_IRWXU | S_IRWXG | S_IRWXO);
    readHere = open(readHere_path, O_RDONLY);

    task *this_task = malloc(sizeof(task));
    this_task->id = 0;

    struct timing *reply_time = malloc(sizeof(struct timing));
    reply_time->minutes = 5; // test vars
    reply_time->hours = 5; // test vars
    reply_time->daysofweek = 5; // test vars

    uint32_t reply_argc;
    read(readHere, &reply_argc, sizeof(reply_argc));
    reply_argc = be32toh(reply_argc);

    // reply_argc should be 2, because we wrote only 2 words "echo" and "test-0"

    command *cmds = NULL;
    for (int j = 0; j < (int) reply_argc; j  ) {
        uint32_t argSize_uint;
        read(readHere, &argSize_uint, sizeof(argSize_uint));
        int argSize = be32toh(argSize_uint);
        int newSize = argSize   1;
        char arg[newSize];
        int data_read = (int) read(readHere, &arg, argSize);
        arg[data_read] = '\0';

        //printf("read '%s' from pipe\n", arg); // THIS PRINTF

        cmds = addToCommand(cmds, newSize, arg);
    }
    this_task->cmd = cmds;
    this_task->next = NULL;

    printf("arg before addTask = '%s'\n", this_task->cmd->argv[0].data);
    addTask(this_task);
    printf("arg after addTask = '%s'\n", this_task->cmd->argv[0].data);

    exit(0);
}



The code who's writing in the pipe:

#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <endian.h>

int main() {

    char *writeHere_path = "saturndReadPipe";

    int writeHere = open(writeHere_path, O_WRONLY | O_TRUNC);

    uint32_t cmd_argc = htobe32(2);
    write(writeHere, &cmd_argc, sizeof(cmd_argc));

    // sending "echo"
    uint32_t length = htobe32(4);
    write(writeHere, &length, sizeof(length));
    char *cmd_data = "echo";
    uint8_t d[4];
    int j = 0;
    for (; j < 4;   j)
        d[j] = cmd_data[j];
    write(writeHere, &d, sizeof(d));

    // sending "test-0"
    length = htobe32(4);
    write(writeHere, &length, sizeof(length));
    cmd_data = "test-0";
    uint8_t dd[4];
    j = 0;
    for (; j < 4;   j)
        dd[j] = cmd_data[j];
    write(writeHere, &dd, sizeof(dd));

    exit(0);
}


CodePudding user response:

You do not copy string only assign the pointer to it. I would do it a bit different way.

typedef struct argument {
    size_t length; // length of the data string
    char data[];
}argument;

typedef struct command {
    int argc; // amount of arguments(words) in argv
    argument *argv[];
}command;

command *addToCommand(command *cmd, const size_t argSize, const char *restrict arg) 
{
    int newargc = cmd ? cmd -> argc   1 : 1;
    argument *currentArgument = malloc(sizeof(*currentArgument)   
             (argSize   1) * sizeof(currentArgument -> data[0]));  //if argsize includes null terminating character remove " 1"  
    if (currentArgument) 
    {
        currentArgument->length = argSize;
        strcpy(currentArgument->data, arg);

        cmd = realloc(cmd, sizeof(*cmd)   newargc * sizeof(cmd -> argv[0]));

        if(cmd)
        {
            cmd -> argc = newargc;
            cmd -> argv[newargc -1] = currentArgument;
        }
    }

    return cmd;
}
  • Related