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;
}