Can someone help me understand how to allocate properly in c? - c

I don't think I properly understand how to allocate memory for what I want to do.
I would like my program to store arguments from the command line into an array of stucts called Command which has char **args in it. for example if I run
./test.c echo hello : ls -l
I want it to store it as this
commands[0].args[0]= echo
commands[0].args[1]= hello
commands[1].args[0]= ls
commands[1].args[1]= -l
But instead my code is storing it in this way
commands[0].args[0]= echo
commands[0].args[1]= hello
commands[0].args[2]= ls
commands[0].args[3]= -l
commands[1].args[0]= ls
commands[1].args[1]= -l
Could someone help me understand why it is storing ls -l in 2 places? Here is my code:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct test {
char **args;
} Command;
int main(int argc, char *argv[])
{
int i, j, k;
Command *commands;
j = k = 0;
commands = (Command *)malloc(argc * sizeof(Command));
for (i = 1; i < argc; i++)
{
if (strcmp(argv[i], ":") == 0)
{
j++;
k = 0;
}
else {
commands[j].args = (char **)realloc(commands[j].args, (k+1) * sizeof(char*));
commands[j].args[k++] = argv[i];
}
}
for (i = 0; i <= j; i++)
{
for (k = 0; k < 5; k++)
{
printf("commands[%d].args[%d]= %s\n", i, k, commands[i].args[k]);
}
}
return EXIT_SUCCESS;
}

Your data storage structure has no way of telling how many strings in commands[j] are valid. So I think it's putting two pointers each in commands[0] and commands[1] just like you expect. But then your print loop looks at commands[0].args[k] for k all the way up to 4, even though it's only valid to look at the first two. When you get up to looking at commands[0].args[2], the result is undefined. (Showing memory from somewhere else in your program, crashing, and catching fire are just a few of the things a program is allowed to do if you use undefined behavior.)
To figure out how many arguments are in each command, you could add a counter member to your struct test. Or maybe allocate one more pointer than there are arguments, and put a NULL after the last argument.

Here is how I would allocate the memory:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct cmd_s {
int num;
char **args;
} cmd_t;
void print_cmds(cmd_t *c, int num) {
int i, j;
for (i=0;i<=num;i++) {
for (j=0;j<c[i].num;j++)
printf("cmds[%d][%d] = %s\n", i, j,c[i].args[j]);
}
}
int main(int argc, char *argv[]) {
int i, j = 0, k = 0;
cmd_t *cmds;
cmds = (cmd_t *)malloc(sizeof(cmd_t));
cmds[0].args = NULL;
cmds[0].num = 0;
for (i=1;i<argc;i++) {
if (strcmp(argv[i], ":") == 0) {
cmds = (cmd_t *)realloc(cmds, (sizeof(cmd_t) * ++j) + 1);
cmds[j].args = NULL;
cmds[j].num = 0;
continue;
}
cmds[j].args = (char **)realloc(cmds[j].args, sizeof(char *) * ++cmds[j].num);
cmds[j].args[cmds[j].num-1] = (char *)malloc(50);
strcpy(cmds[j].args[cmds[j].num-1], argv[i]);
}
print_cmds(cmds, j);
for (i=0;i<=j;i++) {
for(k=0;k<cmds[i].num;k++)
free(cmds[i].args[k]);
free(cmds[i].args);
}
free(cmds);
return 0;
}

Each of your Command structs only have one arg
Perhaps you should consider
typedef struct test {
char **args[5];
} Command;
and then design a better data structure, like a list of lists.

Perhaps you should store the length of args in the struct?
typedef struct test {
char ** args;
unsigned length;
} Command;
Also, maybe you should consider using some of the built in functionality of the C string library. For example, strtok splits a string using the delimiters you give it.

Related

Segmentation fault in a c code, involving multithread

I have problems with my code. It's a multithreading program that executes the following Linux command "# cat | sort | uniq -c | sort -nr". When I try to run the program in a virtual machine, I get a segmentation error, no core dumped. I have tried everything to fix this, but I still get the error. I see that the problem is in the main function and I don't know what it is. Could be either in pthread_join or maybe could be the max number of threads, declared globally. Can someone help me out? This is my code.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define MAX_THREADS 0x40
#define MAX_STRING 124ULL
struct string_count_entry {
char* string;
int count;
};
struct string_count {
int nb_string;
struct string_count_entry* entries;
};
struct string_count* string_count_init() {
struct string_count* sc;
sc = malloc(sizeof(sc));
sc->entries = NULL;
sc->nb_string = 0;
return sc;
}
int addstring(struct string_count* pt, char* s) {
int i;
for (i = 0; i < pt->nb_string; i++) {
if (strcmp(pt->entries[i].string, s))
break;
}
if (i == pt->nb_string) {
pt->entries = realloc(pt->entries,
pt->nb_string + 1 * sizeof(pt->entries[0]));
if (pt->entries == NULL)
return -1;
pt->nb_string++;
pt->entries[i].string = s;
}
pt->entries[i].count++;
return 0;
}
static inline int Compare(const void* pt1, const void* pt2) {
struct string_count_entry* a = malloc(sizeof(pt2));
struct string_count_entry* b = malloc(sizeof(pt1));
if (a->count == b->count)
return strcmp(a->string, b->string);
return a->count - b->count;
}
void string_count_pint(struct string_count* sc) {
int i;
qsort(sc->entries, sc->nb_string, sizeof(struct string_count), Compare);
i = 0;
while (i < sc->nb_string) {
printf("%d %s\n", sc->entries[i].count, sc->entries[i].string);
i++;
}
}
void string_count_free(void* pt) {
struct string_count* sc = malloc(sizeof(pt));
char i;
for (i = 0; i < sc->nb_string; i++) {
free(sc->entries[i].string);
}
free(sc->entries);
}
char* readline(void) {
int i = 0;
char c;
char* linebuf = (char*)malloc(MAX_STRING);
while (read(0, &c, 1) != 0) {
if (c == '\n') {
linebuf[i] = '\0';
return linebuf;
}
linebuf[i++] = c;
}
return NULL;
}
void* thread_main(void* arg) {
struct string_count* sc = malloc(sizeof(arg));
char* line;
while ((line == readline()) != '\0') {
addstring(sc, line);
}
return NULL;
}
int main(int argc, char** argv) {
int nbthreads;
int i;
pthread_t threads[MAX_THREADS];
struct string_count* sc;
if (argc != 1) {
fprintf(stderr, "usage: %s <nb threads>\n", argv[0]);
return EXIT_FAILURE;
}
nbthreads = atoi(argv[1]);
sc = malloc(sizeof(nbthreads));
for (i = 0; i < nbthreads; i++) {
pthread_create(&threads[i], NULL, thread_main, sc);
}
do {
pthread_join(threads[nbthreads--], NULL);
} while (nbthreads > 0);
string_count_free(sc);
string_count_pint(sc);
return EXIT_SUCCESS;
}
I suspect the bug is in this line: sc = malloc(sizeof(nbthreads));
You probably wanted sc = malloc(sizeof(string_count));
I'm also not sure if struct string_count* sc = malloc(sizeof(arg)); does what you intended in thread_main.
You probably need the sc in main be an array and pass a different item in it to each thread and then aggregate them after the join.
Here are the first few errors I have spotted, in no particular order.
Unprotected modification of data structures from multiple threads. Read something about multithreading. Pay attention to the word "mutex".
pthread_join(threads[nbthreads--], NULL); goes out of bounds.
struct string_count* sc = malloc(sizeof(arg)); makes no sense. sizeof(arg) is the size of a pointer (8 on most PC-like systems). This is not enough to hold one struct string_count.
struct string_count_entry* a = malloc(sizeof(pt2)); apparently has even less sense. You are allocating something in a string comparison function, using a wrong size, then you are using the allocated memory without initializing it, and without even trying to compare the things passed to the function.
while ((line == readline()) != '\0') does not assign anything.
pt->entries = realloc(pt->entries, pt->nb_string + 1 * sizeof(pt->entries[0])); is missing a couple of parentheses.

why malloc yields error after long argv arguments?

I have written a program where it reads some filenames and a word from command line arguments. The first argument will be a word and remaining will be filenames. It fills a structure that I have defined.
However for small arguments, the program works correctly but for large ones malloc gives corrupted top size error.
Below is just initial code of the program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILENAME_LIM 256
#define WORD_LIM 256
struct data {
char filename[FILENAME_LIM];
char word[WORD_LIM];
};
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("usage: ./a.out word filename1 filename2 filename3 filename4 filename5 ...\n");
exit(EXIT_FAILURE);
}
char word[WORD_LIM];
strcpy(word, argv[1]);
int files = argc - 2;
struct data *dataarray = (struct data *)malloc(sizeof(sizeof(struct data) * files));
if (!(dataarray)) {
perror("malloc");
exit(EXIT_FAILURE);
}
for (int i = 0; i < files; i++) {
strcpy(dataarray[i].filename, argv[i + 2]);
for (int ii = 0; ii < strlen(dataarray[i].filename) + 1; ii++) {
printf("filename[%d] = %c (%d), argv[%d] = %d\n",
i, dataarray[i].filename[ii], dataarray[i].filename[ii],
i, argv[i + 2][ii]);
}
}
return 0;
}
I tried everything, but when I give some large filename in argv such as "../../../C Programs/chess.c", malloc yields an error. I want to know what is making corrupted top size.
sizeof(struct data) * files
is a valid size. Any multiple of a size is a size.
sizeof(sizeof(struct data) * files)
is like saying sizeof(23422). I don't know what that means, and odds are the runtime isn't behaving properly either.
Restrict your use of sizeof(...) to processing type arguments.

initialize struct from function call

Feel like im taking crazy pills just trying to do literally the simplest stuff I can imagine in C. Any help would be extremely appreciated. why does this work?
#include <stdio.h>
#include <stdlib.h>
#define Q_LIMT 100
typedef struct servers
{
int id;
int num_in_Q;
int server_status;
}SERVER;
void initialize(SERVER *s);
void initialize(SERVER *s)
{
int i=0,j=0;
for(i=0; i<2; i++) { //i=0; i=1
s[i].id = i; // 0, 1
s[i].num_in_Q = i*i + 1; // 1, 2
s[i].server_status = i+i + 2; // 2, 4
} // the bracket was missing
}
int main()
{
int i;
SERVER serv[2];
initialize(serv);
for(i=0; i<2; i++) {
printf("server[%d].id = %d\n", i, serv[i].id);
printf("server[%d].num_in_Q = %d\n", i, serv[i].num_in_Q);
but this throws away the initialized struct?
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
'''
int POINTERS_PER_INODE = 5;
struct Inode {
int valid;/* 0 == invalid, 1 == valid*/
int size;
int Blocks [5];
};
int InodeToString(char * InodeString, struct Inode iNode){
char * blockBuffer;
sprintf(InodeString, "%d", iNode.valid);
int i;
for (i = 0; i < POINTERS_PER_INODE; i++){
blockBuffer = malloc(8);
sprintf(blockBuffer, "%d", iNode.Blocks[i]); //no valid pointers yet
strcat(InodeString,blockBuffer);
free(blockBuffer);
}
return 0;
}
int initializeInode(struct Inode iNode){
int i;
for (i = 0; i < POINTERS_PER_INODE; i++){
iNode.Blocks[i] = -1; //no valid pointers yet
}
iNode.valid = 0; //initialized as invalid inode
return 0;
}
int main() {
struct Inode iNode1;
initializeInode(iNode1);
char * InodeString;
InodeString = malloc(20);
InodeToString(InodeString, iNode1);
printf("%s", InodeString);
free(InodeString);
iNode1.valid = 1;
InodeString = malloc(20);
InodeToString(InodeString, iNode1);
printf("%s", InodeString);
return 0;
}
This is test code btw, so the includes probably dont make sense. stack overflow says I dont have enough details so I guess I have to keep typing sentences. Let me know if theres any details that would make this more clear. its for a basic super simplified file system simulation project. it seemed in a previous version when I initialized the inode outside of the function, I was able to pass the string into the string function, assign it values, not use it as the return value and still end up on the other side of the function with an updated string.
As is normal in C, arguments to a function are passed by value. The object called iNode in initializeInode is local to that function, and changes to it have no effect on any other object in the program. If you want a function to modify an object that's local to the caller, you have to pass a pointer to it, and dereference that pointer to get at the caller's object.
So what you probably want is:
int initializeInode(struct Inode *iNode){
int i;
for (i = 0; i < POINTERS_PER_INODE; i++){
iNode->Blocks[i] = -1; //no valid pointers yet
}
iNode->valid = 0; //initialized as invalid inode
return 0;
}
int main() {
struct Inode iNode1;
initializeInode(&iNode1);
// ...
}

How to pass whole array of words given in command line arguments direct to function?

I want to ask is there a diffrent to pass words from comand line array of strings to this function other than this:
//input given: $> ./main tail degree sheet nose noise base boy
//declaration of function: int ll_insert_words(struct linked_list_t* ll, int N, ...);
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "linked_list.h"
int main(int argc,char** argv) {
if (argc <= 1) {
printf("Not enough arguments");
return 9;
}
struct linked_list_t* ll = ll_create();
if (ll == NULL) {
printf("Failed to allocate memory");
return 8;
}
for (int i = 0; i < argc - 1; i++) {
ll_insert_words(ll, 1, *(argv + 1 + i));
}
ll_display(ll);
ll_clear(ll);
free(ll);
return 0;
}
I want to know how can I pass the array directly to function. By that I mean:
ll_insert_words(ll, 12, "list", "among", "sharp", "has", "coat", "consonant", "old", "trouble", "require", "wear", "band", "real");
But to swap all "list" etc. to the array.
You'll need to pass a (char**) pointer to the function. Change the function declaration to:
int ll_insert_words(struct linked_list_t* ll, char** words, int number_of_words);
And then call it with these parameters:
ll_insert_words(ll, argv, argc);
Then in the function write something along these lines:
for (i = 0; i < number_of_words; i++)
{
ll_insert(ll, words[i]);
}

Whats wrong with this basic shell program? it will run fine for the first few commands but results always ends in a seg fault

I have to build a simple shell program using lex and c code. The lex portion is for breaking down the input. It has been provided for me and I'm not expected to change it. I'm in the process of getting my code to run basic commands like "ls". It seems to work the first few times I run the command but eventually always seg faults. Here is the lex code provided:
%{
int _numargs = 10;
char *_args[10];
int _argcount = 0;
%}
WORD [a-zA-Z0-9\/\.-]+
SPECIAL [()><|&;*]
%%
_argcount=0;
_args[0]=NULL;
{WORD}|{SPECIAL} {
if(_argcount < _numargs-1) {
_args[_argcount++]= (char *)strdup(yytext);
_args[_argcount]= NULL;
}
}
\n return (int)_args;
[ \t]+
.
%%
char **getln() {
return (char **)yylex();
}
This is the C code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
extern char **getln();
int main() {
int i;
char **args;
int child1;
int status1;
int counter=0;
int argCount = 1;
char **array = (char **)malloc(1500 * sizeof(char *));
for (i = 0; i < 1500; ++i) {
array[i] = (char *)malloc(500);
}
strcpy(array[0],"ls\0");
array[1] = NULL;
while(1) {
args = getln();
printf("is error here?");
strcpy(array[0], args[counter]);
for(i = (counter+1); args[i] != NULL; i++) {
printf("\nRight before copying to subarray");
strcpy(array[argCount], args[i]);
argCount++;
}
array[argCount] = NULL;
if (strcmp(args[counter],"exit")==0) exit(0);
child1 = fork();
if(child1==0){
execvp(array[0], array);
printf("Unknown command, please try again.");
exit(1);
}
else{
while (wait(&status1) != child1);
}
for(i = 0; args[i] != NULL; i++) {
printf("Argument %d: %s\n argCount: %d", i, args[i], argCount);
}
argCount = 1;
counter++;
}
}
Thanks in advance for any advice. If there is some simple way to adjust the getln() function to overwrite the args array each time it is called that might be easier than what I am attempting but I have no idea how to go about that.
It seems like you have put
_argcount=0;
_args[0]=NULL;
at the top of the rules section in hopes that these statements would be executed at the beginning of yylex(). And you've noticed that they aren't executed (it keeps appending to the previous values because _argcount never goes back to 0).
The obvious thing to do is move those statements into getln() just before the yylex().
What you have now is a lexer that will ignore the string _argcount=0; in the input because it will match that pattern and there's no action to go with it. The second line is even cooler since the [0] is a character class. It makes the lexer ignore the string _args0=NULL;

Resources