why malloc yields error after long argv arguments? - c

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.

Related

How do you assign structs into an array?

I have currently made this much of the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#define STRSIZE 21
struct PInven{
int count;
struct PItem{
char name[STRSIZE];
int amount;
}Pitem;
}Pinven;//this needs to be an output file
int ReadInProduce (){
//read in file and check to see if the file exist or not.
FILE * PinFile = fopen("produce.txt","r");
if (PinFile == NULL){
printf("ERROR: WRONG FILE");
}
else{
printf("I did it!!\n");
}
//assigning the value gotten into the struct variable(but need to maybe change this since it needs to be an output)
fscanf(PinFile,"%d",&Pinven.count);
printf("%d\n", Pinven.count);
int i;
for(i =0; i <Pinven.count; i++){
fscanf(PinFile,"%20s %d",Pinven.Pitem.name, &Pinven.Pitem.amount);
printf("%s %d\n",Pinven.Pitem.name, Pinven.Pitem.amount);
}
//making an array to hold the variables
//FILE * PoutFile = fopen("produce_update.txt","w");
fclose(PinFile);
return 0;
}
From there I want to get the file that is read to the structs to be printed out into an array so that later on I can make a function that will be able to compare to the to it.
Basically a store management system. Where the file of the inventory is read in and compared to the file that is store and return a new value for the amount of produce now either left or gained.
10 //number of items that will be stored in the store
apple 19
banana 31
broccoli 9
...
In general, it's a really bad idea to include header information in the file about the number of entries in the file. You want to be able to do stream processing, and that will be more difficult if you need that meta-data. More importantly, it is important to understand how to write the code so that you don't need it. It's not really that difficult, but for some reason people avoid it. One simple approach is just to grow the array for each entry. This is horribly inefficient, but for the sake of simplicity, here's an example that expects the file not not include that first line:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <limits.h>
#define STRSIZE 128
struct PItem{
char name[STRSIZE];
int amount;
};
struct PInven{
int count;
struct PItem *PItem;
};
static void
grow(struct PInven *p)
{
p->PItem = realloc(p->PItem, ++p->count * sizeof *p->PItem);
if( p->PItem == NULL ){
perror("out of memory");
exit(1);
}
}
int
ReadInProduce(struct PInven *P, const char *path)
{
FILE * PinFile = fopen(path, "r");
if( PinFile == NULL ){
perror(path);
exit(1);
}
char fmt[64];
int max_len;
max_len = snprintf(fmt, 0, "%d", INT_MAX);
snprintf(fmt, sizeof fmt, "%%%ds %%%dd", STRSIZE - 1, max_len - 1);
grow(P);
struct PItem *i = P->PItem;
while( fscanf(PinFile, fmt, i->name, &i->amount) == 2 ){
i += 1;
grow(P);
}
P->count -= 1;
fclose(PinFile); /* Should check for error here! */
return P->count;
}
int
main(int argc, char **argv)
{
struct PInven P = {0};
char *input = argc > 1 ? argv[1] : "produce.txt";
ReadInProduce(&P, input);
struct PItem *t = P.PItem;
for( int i = 0; i < P.count; i++, t++ ){
printf("%10d: %s\n", t->amount, t->name);
}
}
As an exercise for the reader, you should add some error handling. At the moment, this code simply stops reading the input file if there is bad input. Also, it would be a useful exercise to do fewer reallocations.
you should change Structure of PInven to it can save a dynamic array of Pitem with a Pitem pointer.
tested :
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define STRSIZE 21
typedef struct {
char name[STRSIZE];
int amount;
} Pitem;
struct PInven {
int count;
Pitem *pitem;
} Pinven; // this needs to be an output file
int main() {
// read in file and check to see if the file exist or not.
FILE *PinFile = fopen("produce.txt", "r");
if (PinFile == NULL) {
printf("ERROR: WRONG FILE");
} else {
printf("I did it!!\n");
}
// assigning the value gotten into the struct variable(but need to maybe
// change this since it needs to be an output)
fscanf(PinFile, "%d", &Pinven.count);
Pinven.pitem = (Pitem *)malloc(sizeof(Pitem) * Pinven.count);
printf("%d\n", Pinven.count);
int i;
for (i = 0; i < Pinven.count; i++) {
fscanf(PinFile, "%20s %d", Pinven.pitem[i].name,
&Pinven.pitem[i].amount);
// printf("%s %d\n",Pinven.pitem[i].name, Pinven.pitem[i].amount);
}
for (i = 0; i < Pinven.count; i++) {
printf("%s %d\n", Pinven.pitem[i].name, Pinven.pitem[i].amount);
}
// making an array to hold the variables
// FILE * PoutFile = fopen("produce_update.txt","w");
fclose(PinFile);
// remember free
free(Pinven.pitem);
return 0;
}

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

Storing characters in array using pointers

I am supposed to create an array with the fixed size (let’s say 5x5). I am supposed to fill it with words typed as command line parameters. I can use only pointers. Obviously I have to create two dimensional array[5][5]. I can’t use more than 25 letters ( I will make if statements ). I am going replace white space with some symbol ($ or something). The problem is I don’t know how to connect those command line parameters with array using only pointers.
You need to use the argc and argv arguments from the main function.
Here is an example.
#include <stdio.h>
int main(int argc, char *argv[])
{
for (unsigned i = 1; i < argc; i++)
{
printf("Word %u is: %s\n", i, argv[i]);
}
return 0;
}
You compile it using gcc main.c -o a.exe.
And run it using a.exe hello world.
Edit:
Further to your comment.
You can create an array of pointers like so:
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *my_array_of_strings[5]; // up to 5 strings
// populate your array
for (unsigned i = 1; i < argc; i++)
{
my_array_of_strings[i - 1] = malloc(strlen(argv[i]) + 1);
if (NULL == my_array_of_strings[i - 1])
{
printf("oh no, memory failure");
break;
}
memcpy(my_array_of_strings[i - 1], argv[i], strlen(argv[i]) + 1);
printf("word is %s\n", my_array_of_strings[i - 1]);
}
return 0;
}

SHA_256 functions corrupting memory space

I've been trying to use the SHA_256 functions in sha256.h on a FreeBSD 9.1 system but it seems to be corrupting memory space of my program causing all kinds of manic behavior. I wrote up a quick program to just to play with those functions and still am having problems.
In the example below, int i is changed when I call SHA256_Init(), as shown by the output from the printf() statements surrounding it.
This is what I get running the code.
$ ./miner "hello world"
i = 0
i = 32
0000000032 9010a9cf81ce2c28a642fd03ddf6da5790c65c30cd4a148c4257d3fe488bacc7
Why is this value changing to 32? Am I missing something? The code is below...
#include <sha256.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#define DIFFICULTY 0
int main(int argc, const char **argv) {
uint nonce, i, j;
SHA256_CTX ctx;
size_t arglen;
unsigned char digest[32];
char * data;
if(argc < 1) exit(1);
arglen = strlen(argv[1]);
data = malloc(arglen + 1);
char digestStr[65];
i = 0;
do {
nonce = i;
strncpy(data, argv[1], arglen + 1);
printf("i = %i\n", i);
SHA256_Init(&ctx);
printf("i = %i\n", i);
SHA256_Update(&ctx, data, arglen);
SHA256_Update(&ctx, (unsigned char *) &nonce, sizeof(nonce));
SHA256_Final(digest, &ctx);
SHA256_End(&ctx, digestStr);
printf("%010i\t%s\n", i, digestStr);
j = 0;
while(j < 32 && digest[j] == '\0') {
j++;
}
i++;
} while(j < DIFFICULTY);
free(data);
return 0;
}
I just had this exact same problem and solved it.
The issue is that your are including a different header in your code than the SHA2 library you linked into your application is using.
In my case the SHA256_CTX struct was a different size in the openSSL library. The openSSL library's struct was 8 bytes bigger than the struct length in the file.
The function SHA256_Init(&ctx) does a memset on the SHA256_CTX struct which then corrupts 8 extra random bytes after the struct. I say random because it will do different things in a release vs debug build because the optimizing compiler will move your variables around.

Can someone help me understand how to allocate properly in 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.

Resources