C array of struct issues - c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct individual {
char name[32];
int stats[7];
char role;
};
void create_array(struct individual **array){
*array = malloc(sizeof(struct individual)); //allocate initial memory space
}
void resize_array(struct individual **array, unsigned char num) {
printf("%d\n", *array);
*array = realloc(*array, num * sizeof(struct individual));
printf("%d\n", *array);
printf("resize success\n");
}
void problem(struct individual **f_array, unsigned char *f_num) {
*f_num = 2;
printf("%d\n", *f_array);
resize_array(f_array, *f_num);
printf("%d\n", *f_array);
strcpy(f_array[*f_num - 1]->name, "test value"); //CRASH LINE
}
int main() {
unsigned char f_num = 0;
struct individual *f_array;
create_array(&f_array);
problem(&f_array, &f_num);
}
This code crashes on the line marked "CRASH LINE". While it is not shown here, doing this same code setting (*f_num = 1) does not result in an error. While passing *f_array as itself (with appropriate alterations to the code in problem) does not result in an error, the values given after problem is exited result in nonsense being given, as the pointer reverts to it's pre-resize state. Any help appreciated.

The problem is the line accessing that value.
The line should read like this:
strcpy((*f_array)[*f_num - 1].name, "test value"); // doesn't crash any more :)
To break it down a little bit:
f_array is a pointer to the array of structs, need to dereference it before indexing
[*f_num - 1] accesses element 1 of the array.

Related

Automatic generation of struct printing function in C

I have many programs where structs are defined. And each time, I have to create a function to print the members. For example,
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
void printMyStruct(myStruct myPeople) {
printf("%s\n",myPeople.name);
printf("%s\n",myPeople.address);
printf("%d\n",myPeople.zip);
}
int main()
{
myStruct myPeople={"myName" , "10 myStreet", 11111};
printMyStruct(myPeople);
}
I know that reflection is not supported in C. And so, I write these printing functions for each struct I defined.
But, I wonder if it exists any tricks to generate automatically these printing functions. I would understand that I have to modify a little bit these functions. But, if a part of the job is done automatically, it would be great.
(This example is simple, sometimes struct are nested or I have array of structs or some fields are pointers, ...)
You can of-course print structs, but expect a lot of non-readable output:
#include <stdio.h>
#include <ctype.h>
struct example {
int x;
int y;
char c;
};
#define NOT_PRINTABLE "Not Printable"
void print_structure(const char *structure, size_t size) {
for (size_t i = 0; i < size; i++) {
printf("%ld)\t%.2X: %.*s\n", i, structure[i],
(isprint(structure[i]) ? 1 : sizeof(NOT_PRINTABLE) - 1),
(isprint(structure[i]) ? &structure[i] : NOT_PRINTABLE));
}
}
int main(int argc, char **argv) {
struct example a;
a.x = 5;
a.y = 6;
a.c = 'A';
print_structure((char *)&a, sizeof(struct example));
return 0;
}
But the issue is that, it will print the structs as it is represented in memory. So 4 byte (32 bit) integer 1 will be represented with 4 bytes, not the char '1'.
And due to the way pointers work, you cannot make out if a member is a pointer or a non-pointer.
Another issue is that structures have padding to help with alignment, and better/efficent use of memory. So you would see a lot of 0x00 in the middle.
Remember that C is a compiled language.
let's consider to use https://copilot.github.com/. it's great.
this is what i have with copilot
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
//print struct myStruct >> auto generate by codepilot after you type a comment `print struct myStruct`
void printStruct(myStruct *s) {
printf("name: %s\n", s->name);
printf("address: %s\n", s->address);
printf("zip: %d\n", s->zip);
}

Problem with calling realloc inside function where an array is a parameter [duplicate]

This question already has an answer here:
C Passing Pointer to Pointer to a Function and Using malloc
(1 answer)
Closed 2 years ago.
I have a problem with realloc. Valgrind returns 8 bytes in 1 blocks are definitely lost in loss record 1 of 1. Whereas if I called the function allocate from main, it works. I don't understand what is the difference? It works if I put free(tab) inside the functionsth but I need to do something with tab inside main. Can anyone help find a solution?
#include <stdio.h>
#include <stdlib.h>
struct x{
int a;
char b;
};
void allocate( struct x **tab,int *size)
{
*size = 1+2*(*size);
*tab= realloc(*tab, (size_t) (*size) * sizeof (**tab));
}
void sth (struct x *tab, int *size)
{
//do something here
allocate(&tab, size);
}
int main(void)
{
int size=0;
struct x *tab=NULL;
sth(tab, &size);
//do sth here with tab
free(tab);
return 0;
}
The argument tab of the function sth is a copy of what is passed and change to that won't affect what is passed. Therefore, free(tab); in the main() function means free(NULL);. This is defined to do nothing and it won't contribute for avoiding memory leak. Pass pointers to what should be modified to have functions modify what are passed.
#include <stdio.h>
#include <stdlib.h>
struct x{
int a;
char b;
};
void allocate( struct x **tab,int *size)
{
*size = 1+2*(*size);
*tab= realloc(*tab, (size_t) (*size) * sizeof (**tab));
}
void sth (struct x **tab, int *size) // receive a pointer of struct x*
{
//do something here
// allocate(&(*tab), size);
allocate(tab, size);
}
int main(void)
{
int size=0;
struct x *tab=NULL;
sth(&tab, &size); // pass a pointer to what should be modified
//do sth here with tab
free(tab);
return 0;
}

What am I doing wrong in passing a struct around in C?

So I am working on a project in C that requires that I pass pointers to a struct into functions. The project is structured as follows:
struct structName {
unsigned short thing2;
char thing1[];
};
void function_1(struct structName *s) {
strcpy(s->thing1, "Hello");
printf("Function 1\n%s\n\n", s->thing1); // prints correctly
}
void function_2(struct structName *s) {
// can read thing2's value correctly
// thing1 comes out as a series of arbitrary characters
// I'm guessing it's an address being cast to a string or something?
printf("Function 2\n%s\n\n", s->thing1); // prints arbitrary characters ('É·/¨')
}
int main() {
struct structName s;
function_1(&s);
printf("Main\n%s\n\n", s.thing1);
function_2(&s);
printf("Main 2\n%s\n\n", s.thing1);
}
This code outputs the following:
Function 1
Hello
Main
Hello
Function 2
É·/¨
Main 2
É·/¨
Obviously, the program has more than just what I've written here; this is just a simplified version; so if there's anything I should check that might be causing this let me know. In all honesty I reckon it's probably just a stupid rookie error I'm making somewhere.
[EDIT: Seems like s.thing1 is being mutated in some way in the call to function_2(), since the odd value is replicated in main() - I should point out that in my program the printf()s are located right before the function call and in the first line of the function, so there's no chance that it's being written to by anything I'm doing. I've updated the example code above to show this.]
Thanks in advance!
The structure contains a flexible member at its end, if you declare a static object with this type, the length of this member will be zero, so strcpy(s->thing1, "Hello"); will have undefined behavior.
You are supposed to allocate instances of this type of structure with enough extra space to handle whatever data you wish to store into the flexible array.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct pstring {
size_t length;
char data[];
} pstring;
pstring *allocate_pstring(const char *s) {
size_t length = strlen(s);
pstring *p = malloc(sizeof(*p) + length + 1);
if (p != NULL) {
p->length = length;
strcpy(p->data, s);
}
return p;
}
void free_pstring(pstring *p) {
free(p);
}
int main() {
pstring *p = allocate_pstring("Hello");
printf("Main\n%.*s\n\n", (int)p->length, p->data);
free_pstring(p);
return 0;
}

C: sha256 hash function outputs in fields of structure array inducing crash when writing structure contents to disk

I am attempting to write a program which will store credential information in an array of structures and then print that information out into a file (this is for learning purposes only, don't worry). To do this, I create an array of structures and then raster through that array to assign the pertinent information to each field. This proceeds without issue. I then attempt to raster through the array again to write each structure's fields to a file whereupon the program crashes after the first write (ie only one structure's worth of content is successfully written to the output file).
I created the following simplified / stripped down variant of my program which reproduces the error. I believe the problem lies within the set_hash_entry function as the error only manifested after that function was re-introduced into my stripped down code in place of a hard coded test value.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "openssl/sha.h"
#include <time.h>
#include <math.h>
struct password_struct {
char password[17];
char hash[65];
float entropy;
};
struct password_struct* allocate_heap_memory(int num_passwords);
void orchestrate_value_setting(int num_passwords, struct password_struct* user_password_structs);
void orchestrate_file_output(int num_passwords, struct password_struct* user_password_structs);
void write_results_to_disk(char file_name[], struct password_struct* user_password_structs);
void set_hash_entry(struct password_struct* user_password_structs);
int main(void) {
int num_passwords = 2;
struct password_struct* user_password_structs = allocate_heap_memory(num_passwords);
struct password_struct* allocated_memory_start_ptr = user_password_structs;
orchestrate_value_setting(num_passwords, user_password_structs);
user_password_structs = allocated_memory_start_ptr; // Resetting pointer to allow cycling back through all structures for appending data to output file
orchestrate_file_output(num_passwords, user_password_structs);
free(allocated_memory_start_ptr);
}
struct password_struct* allocate_heap_memory(int num_passwords) {
struct password_struct* user_password_structs = malloc(num_passwords * sizeof(struct password_struct));
if (!user_password_structs) {
printf("Malloc failed, exiting\n");
exit(0);
}
return user_password_structs;
}
void set_hash_entry(struct password_struct* user_password_structs){
int pass_entry_length = strlen(user_password_structs->password);
SHA256_CTX context;
unsigned char generated_hash[65]; //sha256 standard digest length + 1;
SHA256_Init(&context);
SHA256_Update(&context, (unsigned char *)user_password_structs->password, pass_entry_length);
SHA256_Final(generated_hash, &context);
char* hash_ptr = &user_password_structs->hash[0];
int i;
for (i=0; i < (64); i++) {
snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]); // Need to convert from hex to char representation
}
user_password_structs->hash[64] = '\0';
printf("%s\n", user_password_structs->hash);
}
void orchestrate_value_setting(int num_passwords, struct password_struct* user_password_structs) {
char pw1[10] = "test";
char pw2[10] = "test2";
float entropy1 = 5.0;
float entropy2 = 10.0;
strcpy(user_password_structs->password, pw1);
set_hash_entry(user_password_structs);
user_password_structs->entropy = entropy1;
user_password_structs++;
strcpy(user_password_structs->password, pw2);
set_hash_entry(user_password_structs);
user_password_structs->entropy = entropy2;
user_password_structs++;
}
void orchestrate_file_output(int num_passwords, struct password_struct* user_password_structs) {
printf("Writing data to disk...\n");
char file_name[20] = "name";
int i;
for (i = 0; i < num_passwords; i++) {
write_results_to_disk(file_name, user_password_structs);
user_password_structs++;
}
}
void write_results_to_disk(char file_name[], struct password_struct* user_password_structs) {
FILE *file_pointer = fopen(file_name, "a");
if (file_pointer == NULL) {
printf("Error: Failed to open file\n");
exit(1);
}
fprintf(file_pointer, "%s:%s:%f\n", user_password_structs->password, user_password_structs->hash, user_password_structs->entropy);
fclose(file_pointer);
}
After running this program, the following output is produced:
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
Writing data to disk...
*** Error in `./diagnostic': free(): invalid next size (normal): 0x0804b0c0 ***
Aborted (core dumped)
I naively assumed this was an overflow issue related to my
snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]);
operation, but increasing the size of the hash buffer in the struct does not seem to help. Any help would be greatly appreciated!
I compiled as follows: gcc -o diagnostic -g diagnostic.c -lcrypto -lm
char hash[65];
Okay, hash has room for 65 characters.
char* hash_ptr = &user_password_structs->hash[0];
So, hash_ptr points to hash, so it points to room for 65 characters.
for (i=0; i < (64); i++) {
snprintf(&hash_ptr[i*2], (64), "%02x", generated_hash[i]); // Need to convert from hex to char representation
}
When i is 60, i*2 is 120. So you're trying to write to the 120th position of a buffer with room for 65 characters.
Change that (64) to 32 in the loop or change hash[65] to a bigger buffer.
Using valgrind found this immediately. You should learn to use some too that detects buffer overflows, use after free, double frees, and similar problems.

Pointers to structures, fields changing values inexplicably

I'm fully prepared to be told that I'm doing something stupid/wrong; this is what I expect.
I'm getting a feel for structures and coming a cropper when it comes to accessing the fields from the pointers. Code to follow.
matrix.h:
#ifndef MATRIX_H_INCLUDED
#define MATRIX_H_INCLUDED
#include <stdlib.h>
typedef struct
{
size_t size;
int* vector;
} vector_t;
#endif // MATRIX_H_INCLUDED
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "matrix.h"
vector_t* vector_new(size_t size)
{
int vector[size];
vector_t v;
v.size = size;
v.vector = vector;
return &v;
}
int main(int argc, char* argv[])
{
vector_t* vec = vector_new(3);
printf("v has size %d.\n", vec->size);
printf("v has size %d.\n", vec->size);
return EXIT_SUCCESS;
}
So this is a very simple program where I create a vector structure of size 3, return the pointer to the structure and then print its size. This, on the first print instance is 3 which then changes to 2686668 on the next print. What is going on?
Thanks in advance.
You are returning a pointer to a local variable v from vector_new. This does not have a slightest chance to work. By the time vector_new returns to main, all local variables are destroyed and your pointer points to nowhere. Moreover, the memory v.vector points to is also a local array vector. It is also destroyed when vector_new returns.
This is why you see garbage printed by your printf.
Your code has to be completely redesigned with regard to memory management. The actual array has to be allocated dynamically, using malloc. The vector_t object itself might be allocated dynamically or might be declared as a local variable in main and passed to vector_new for initialization. (Which approach you want to follow is up to you).
For example, if we decide to do everything using dynamic allocation, then it might look as follows
vector_t* vector_new(size_t size)
{
vector_t* v = malloc(sizeof *v);
v->size = size;
v->vector = malloc(v->size * sizeof *v->vector);
return v;
}
(and don't forget to check that malloc succeeded).
However, everything that we allocated dynamically we have to deallocate later using free. So, you will have to write a vector_free function for that purpose.
Complete re-write of answer to address your question, and to provide alternate approach:
The code as written in OP will not compile: &v is an illegal return value.
If I modify your code as such:
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
size_t size;
int* vector;
} vector_t;
vector_t* vector_new(size_t size)
{
int vector[size];
vector_t v, *pV;
pV = &v;
pV->size = size;
pV->vector = vector;
return pV;
}
int main(int argc, char* argv[])
{
vector_t* vec = vector_new(3);
printf("v has size %d.\n", vec->size);
printf("v has size %d.\n", vec->size);
getchar();
return EXIT_SUCCESS;
}
It builds and runs, but returns unintended values for vec->size in main() due to the local scope of that variable in the function vector_new.
Recommend creating globally visible instance of your struct, and redefine vector_new() to int initVector(void):
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
typedef struct
{
size_t size;
int* vector;
} vector_t;
vector_t v, *pV;//globally visible instance of struct
int initVector(void)
{
int i;
pV->size = SIZE;
pV->vector = calloc(SIZE, sizeof(int));
if(!pV->vector) return -1;
for(i=0;i<SIZE;i++)
{
pV->vector[i] = i;
}
return 0;
}
int main(int argc, char* argv[])
{
int i;
pV = &v; //initialize instance of struct
if(initVector() == 0)
{
printf("pV->size has size %d.\n", pV->size);
for(i=0;i<SIZE;i++) printf("pV->vector[%d] == %d.\n", i, pV->vector[i]);
}
getchar(); //to pause execution
return EXIT_SUCCESS;
}
Yields these results:
You still need to write a freeVector function to undo all the allocated memory.

Resources