Is INT in struct tab need to be malloc? - c

I've the following code :
int parser_start(t_control *shell)
{
int i;
int c;
int count;
int separator;
count = 0;
shell->command_index = 1;
shell->commands = malloc(parser_count_separators(shell));
shell->commands[count] = malloc(sizeof(shell->commands));
shell->commands[count]->command = malloc(my_strlen(shell->cli) * sizeof(char));
shell->commands[count]->op = 0;
i = 0;
c = 0;
while (shell->cli[i] != '\0')
{
separator = parser_is_separator(shell->cli[i], shell->cli[i + 1]);
if (separator == -1)
shell->commands[count]->command[c++] = shell->cli[i];
else
{
shell->command_index++;
count++;
shell->commands[count] = malloc(sizeof(shell->commands));
shell->commands[count]->command = malloc(my_strlen(shell->cli) * sizeof(char));
shell->commands[count]->op = separator;
my_printf("%d\n", shell->commands[count]->op);
c = 0;
}
i = i + parser_separator_get_size(separator);
}
}
With the following struct :
typedef struct s_command
{
char *command;
char *program;
char **argv;
int argc;
pid_t pid;
int op;
} t_command;
typedef struct s_control
{
pid_t pid;
char **env;
char **path;
char *cli;
int fd_history;
int power;
int pipefd[2];
int command_index;
char **builtins;
int (*builtins_fptr[6])(struct s_control *, int );
t_command **commands;
} t_control;
When I dump shell->commands[count]->op with my printf, it print 1 as I want.
When I dump the same emplacement in another function I got 7564320.
Why ? Does my op field needs to be malloc too?
Thanks

While it is hard to tell without seeing more code, the most likely culprit is:
shell->commands = malloc(parser_count_separators(shell));
It's clear that the commands field of the t_control structure is a pointer. Without seeing the code for parser_count_separators, it is hard to know for certain, but it seems reasonable that parser_count_separators(shell) will return a count of separators, and that the size of commands should be either
parser_count_separators(shell) * sizeof *shell->commands)
or
(parser_count_separators(shell) + 1) * sizeof *shell->commands)
depending on whether parser_count_separators actually counts separators as its name implies, or counts subcommands (which is one more than the number of separators).

Related

errors with structure save and load function

#include <stdio.h>
#include <stdlib.h>
struct birdhome{
int area;
int heightcm;
int feederquantity;
char hasNest[6];
};
struct bird{
char isRinged[6];
char nameSpecies[50];
int birdAgeMonths;
struct BirdHome *hom;
char gender[7];
};
int save(char * filename, struct bird *st, int n);
int load(char * filename);
int main(void)
{
char * filename = "birds.dat";
struct bird birds[] = { "True","sparrow",3,10,20,2,"False","Male","False","crane",24,50,100,6,"True","Female","False","False","griffin",10,100,80,1,"False","Male" };
int n = sizeof(struct bird) / sizeof(birds[0]);
save(filename, birds, n);
load(filename);
return 0;
}
int save(char * filename, struct bird * st, int n)
{
FILE * fp;
char *c;
int size = n * sizeof(struct bird);
if ((fp = fopen(filename, "wb")) == NULL)
{
perror("Error occured while opening file");
return 1;
}
c = (char *)&n;
for (int i = 0; i<sizeof(int); i++)
{
putc(*c++, fp);
}
c = (char *)st;
for (int i = 0; i < size; i++)
{
putc(*c, fp);
c++;
}
fclose(fp);
return 0;
}
int load(char * filename){
FILE * fp;
char *c;
int m = sizeof(int);
int n, i;
int *pti = (int *)malloc(m);
if ((fp = fopen(filename, "r")) == NULL)
{
perror("Error occured while opening file");
return 1;
}
c = (char *)pti;
while (m>0)
{
i = getc(fp);
if (i == EOF) break;
*c = i;
c++;
m--;
}
n = *pti;
struct bird * ptr = (struct bird *) malloc(n * sizeof(struct bird));
c = (char *)ptr;
while ((i= getc(fp))!=EOF)
{
*c = i;
c++;
}
printf("\n%d birds in the file stored\n\n", n);
for (int k = 0; k<n; k++)
{
printf("%-10d %-6s %-50s %-24d %-100d %-100d %-10d %-10s %-10s \n", k + 1, (ptr + k)->isRinged, (ptr + k)->nameSpecies,(ptr + k)->birdAgeMonths,(ptr + k)->hom.area,(ptr + k)->hom.heightcm,(ptr + k)->hom.feederquantity,(ptr + k)->hom.hasNest,(ptr + k)->gender);
}
Well, the program is theoretically running. The problem is with the printf inside the load function.
The error says that all the structure types that come in struct Birdhome is a
pointer and that I should use -> instead of . in it.
But when I do this it says that I should change the . to ->.
The problem is that bird.hom is a pointer. Saving a pointer to a file is not a useful thing to do, because memory addresses change from one process to another. It's also not saving the contents of the BirdHome structure. And your initialization of birds doesn't work, because you can't initialize members of an indirect structure as part of the main structure.
You should declare it as an embedded structure rather than a pointer.
struct bird{
char isRinged[6];
char nameSpecies[50];
int birdAgeMonths;
struct BirdHome hom;
char gender[7];
};
Declaring it as a pointer would be useful if you wanted a dynamically-sized array of homes, or you wanted to allow multiple birds to reference the same BirdHome structure. If that's what you really need, you'll need to redesign your save and load functions so they dereference the pointer and save what it points to. And if you have a dynamically-sized array of BirdHome, you need to include the array size in bird.
Other errors in your code:
You have an extra "False" in the initialization list of birds. It should be:
struct bird birds[] = { "True","sparrow",3,10,20,2,"False","Male","False","crane",24,50,100,6,"True","Female","False","griffin",10,100,80,1,"False","Male" };
Your calculation of n is incorrect. It should be:
int n = sizeof(birds) / sizeof(birds[0]);

Dynamically allocated string matrix in C

I'm trying to create a string matrix in C to stores the results of a sql callback. For some reason, it always crashes on the 12th reallocation of "data" even though the memory address of data is the same.
Thanks.
int row_index;
static int db_select_cb(void *p_data ,int argc, char **argv, char **azColName){
char ***data = (char ***)p_data;
data = (char ***)realloc(data,sizeof(char **)*(row_index+1));
data[row_index] = (char **)malloc(sizeof(char *)*(argc));
for(int col_index = 0;col_index < argc;col_index++){
data[row_index][col_index] = (char *)malloc(sizeof(char)*(strlen(argv[col_index])+1));
strcpy(data[row_index][col_index],argv[col_index]);
}
row_index++;
return 0;
}
char ***db_select(sqlite3 *conn,unsigned char *zSQL){
row_index = 0;
char ***data = (char ***)malloc(sizeof(char ***)*(row_index+1));
char *err = 0;
int cerr = sqlite3_exec(conn,zSQL,db_select_cb,(void*)data,&err);
if(cerr){
printf(":: SQL ERROR IN \"db_select\" || %s ||\n", err);
sqlite3_free(err);
return 0;
}
return data;
}
Thanks for your help guys. The problem was that I needed to pass a reference to the matrix to the callback as realloc was modifying data. Here's what ended up working.
int row_index;
static int db_select_cb(void *p_data ,int argc, char **argv, char **azColName){
char ****data = (char ****)p_data;
*data = realloc(*data,sizeof(char **)*(row_index+1));
(*data)[row_index] = malloc(sizeof(char *)*(argc));
for(int col_index = 0;col_index < argc;col_index++){
(*data)[row_index][col_index] = malloc(sizeof(char)*(strlen(argv[col_index])+1));
strcpy((*data)[row_index][col_index],argv[col_index]);
}
row_index++;
return 0;
}
char ***db_select(sqlite3 *conn,unsigned char *zSQL){
row_index = 0;
char ***data = malloc(sizeof(char **)*(row_index+1));
char *err = 0;
int cerr = sqlite3_exec(conn,zSQL,db_select_cb,(void*)&data,&err);
if(cerr){
printf(":: SQL ERROR IN \"db_select\" || %s ||\n", err);
sqlite3_free(err);
return 0;
}
return data;
}
Here is an updated solution using structs which as Groo pointed out is the only way to keep track of the row and columns sizes.
typedef struct{
char ***data;
int row_size;
int *col_size;
}Table;
static int db_select_cb(void *p_table ,int argc, char **argv, char **azColName){
Table **table = (Table **)p_table;
(*table)->data = realloc((*table)->data,sizeof(char **)*((*table)->row_size+1));
(*table)->data[(*table)->row_size] = malloc(sizeof(char *)*(argc));
(*table)->col_size = realloc((*table)->col_size,sizeof(int)*((*table)->row_size+1));
int col_index;
for(col_index = 0;col_index < argc;col_index++){
(*table)->data[(*table)->row_size][col_index] = malloc(sizeof(char)*(strlen(argv[col_index])+1));
strcpy((*table)->data[(*table)->row_size][col_index],argv[col_index]);
}
(*table)->col_size[(*table)->row_size] = col_index;
(*table)->row_size++;
return 0;
}
Table *db_select(sqlite3 *conn,unsigned char *zSQL){
Table *table = malloc(sizeof(Table));
table->row_size = 0;
table->data = NULL;
table->col_size = NULL;
char *err = 0;
int cerr = sqlite3_exec(conn,zSQL,db_select_cb,(void*)&table,&err);
if(cerr){
printf(":: SQL ERROR IN \"db_select\" || %s ||\n", err);
sqlite3_free(err);
return 0;
}
return table;
}
Your life would be much easier if you would create a couple of sanely named structs and some tiny helper functions.
First of all, your db_select function returns an allocated data, but sets a global variable row_index. Number of columns is lost forever. But this already indicates that you need a struct - you want to pack all information that this function needs to give you into a single "coherent" block.
So, you might say a row is a bunch of columns:
typedef struct {
char *cols;
int cols_count;
} Row;
And a table is a bunch of rows:
typedef struct {
Row * rows;
int rows_count;
} Table;
And now you handle allocation and housekeeping separately (note: I am writing this in the browser, haven't even checked if it will compile):
// allocates a new table
Table * Table_create(void) {
Table * table = calloc(1, sizeof *table);
return table;
}
// creates a new child row in the table, with the specified number of cols
Row * Row_create(Table *table, int numCols) {
table = realloc(table, table->rows_count * sizeof *table);
table->rows_count++;
Row * newRow = &table->rows[table->rows_count - 1];
newRow->cols = calloc(numCols * sizeof *newRow->cols);
newRow->cols_count = numCols;
return newRow;
}
Sqlite functionality now looks quite simpler:
// this obviously allocates a new table, so somebody will have to
// free it at some point
Table * table_fetch_from_db(sqlite3 * conn, unsigned char * sql) {
Table * table = Table_create();
if (sqlite3_exec(conn, sql, load_single_row, table, NULL)) {
// handle error
}
return table;
}
int load_single_row(void *args, int numCols, char **cols, char **colNames) {
// we passed a Table* as args
Table * table = (Table*)args;
// allocate a new row inside table
Row * row = Row_create(table, numCols);
for (int i = 0; i < numCols; i++) {
int single_col_len = strlen(cols[col_index]);
row->cols[i] = malloc(single_col_len * sizeof *row->cols[i]);
strcpy(row->cols[i], cols[i]);
}
return 0;
}
If you're using C99, this code might be slightly simplified using flexible array members, because you don't need to allocate the struct and the inner array separately.
Note that I haven't tested any of this, it lacks functions for freeing tables, and possibly won't fix your actual issue. :)

Using an array of structures with call by reference

Here is my problem: I have to make this program for school and I spent the last hour debugging and googling and haven't found an answer.
I have an array of structures in my main and I want to give that array to my function seteverythingup (by call by reference) because in this function a string I read from a file is split up, and I want to write it into the structure but I always get a SIGSEV error when strcpy with the struct array.
This is my main:
int main(int argc, char *argv[])
{
FILE* datei;
int size = 10;
int used = 0;
char line[1000];
struct raeume *arr = (raeume *) malloc(size * sizeof(raeume*));
if(arr == NULL){
return 0;
}
if(argc < 2){
return 0;
}
datei = fopen(argv[1], "rt");
if(datei == NULL){
return 0;
}
fgets(line,sizeof(line),datei);
while(fgets(line,sizeof(line),datei)){
int l = strlen(line);
if(line[l-1] == '\n'){
line[l-1] = '\0';
}
seteverythingup(&line,arr,size,&used);
}
ausgabeunsortiert(arr,size);
fclose(datei);
return 0;
}
and this is my function:
void seteverythingup(char line[],struct raeume *arr[], int size,int used)
{
char *token,raumnummer[5],klasse[6];
int tische = 0;
const char c[2] = ";";
int i=0;
token = strtok(line, c);
strcpy(raumnummer,token);
while(token != NULL )
{
token = strtok(NULL, c);
if(i==0){
strcpy(klasse,token);
}else if(i==1){
sscanf(token,"%d",&tische);
}
i++;
}
managesize(&arr[size],&size,used);
strcpy(arr[used]->number,raumnummer);
strcpy(arr[used]->klasse,klasse);
arr[used]->tische = tische;
used++;
}
Edit: Since there is more confusion I wrote a short program that works out the part you are having trouble with.
#include <cstdlib>
struct raeume {
int foo;
int bar;
};
void seteverythingup(struct raeume *arr, size_t len) {
for (size_t i = 0; i < len; ++i) {
arr[i].foo = 42;
arr[i].bar = 53;
}
}
int main() {
const size_t size = 10;
struct raeume *arr = (struct raeume*) malloc(size * sizeof(struct raeume));
seteverythingup(arr, size);
return 0;
}
So basically the signature of your functions is somewhat odd. Malloc returns you a pointer to a memory location. So you really dont need a pointer to an array. Just pass the function the pointer you got from malloc and the function will be able to manipulate that region.
Original Answer:
malloc(size * sizeof(raeume*));
This is probably the part of the code that gives you a hard time. sizeof returns the size of a type. You ask sizeof how many bytes a pointer to you raeume struct requires. what you probably wanted to do is ask for the size of the struct itself and allocate size times space for that. So the correct call to malloc would be:
malloc(size * sizeof(struct raeume));

Pointer to string not incrementing (C programming)

I have two string shown below:
char code *text_to_compare = "TesT";
char code *dictionary = "TesTT,Tes,Tes,TesT.";
In a part of the program I used the following code where it increments the pointers for both strings to point to the next characters.
ch_A = text_to_compare[i++];
ch_B = dictionary[j++];
Why is pointer j being incremented but pointer i is remaining as it was?
Thanks in advance.
EDIT: Below is the full code. The aim of this project is to compare a string with a list of words. Integer i is not incrementing only after the program enters the else statement.
#include <string.h>
char code *text_to_compare = "TesT";
char code *dictionary = "TesTT,Tes,Tes,TesT.";
int bring_characters(char pdata *, char pdata *, char ch_A, char ch_B, char i,
char j);
void main(void) {
unsigned char ch_A;
unsigned char ch_B;
unsigned char i = 0;
unsigned char j = 0;
char pdata N1;
char pdata N2;
int result;
ch_A = text_to_compare[i]; // take a caharacter from the text
ch_B = dictionary[j];
result = bring_characters(&N1, &N2, ch_A, ch_B, i, j);
if (result == 0) {
while (1)
;
}
else {
while (1)
;
}
while (1)
;
}
int bring_characters(char pdata *N1, char pdata *N2, char ch_A, char ch_B,
char i, char j) {
do {
if (ch_A == ch_B) {
ch_A = text_to_compare[i++]; // take a caharacter from the text
ch_B = dictionary[j++];
if ((ch_A == '\0') && ((ch_B == ',') || (ch_B == '.'))) {
while (1)
; // load idata-------------------------------------------------------------------------------------------------
}
}
else {
i = 0; // refresh pointer
ch_A = text_to_compare[i]; // take a caharacter from the text
ch_B = dictionary[j++];
}
} while (ch_B != '.');
return (0);
}
Whew, there's a lot going on here! Now that you've added the full code it looks like in your attempt to move on to the next word you have prevented yourself from moving on.. you'll need to do some major revisions to get this guy working.
The first thing you need to do is figure out how you would do this on paper, then step by step try to reproduce that in your code.
Here's a function to kickstart you:
int find_next_match(char toFind, int startingPosition, char* mainString){
int counter = startingPosition;
char buf = mainString[counter];
while(buf != NULL){
if (buf == toFind){
return counter;
}
counter++;
buf = mainString[counter];
}
return -1; //error
}
You can use something like this to find the next instance of the first character in your string, then you can implement a loop to determine if that is a match.
Good luck, you can do it!

C reference gone after for loop

i got a problem with my C code.
int split(char* source, char*** target, char* splitChar) {
int i;
int currentLength;
int splitCharPosition;
char* currentSubstring = source;
int splitCount = charcount(source, splitChar) + 1;
*target = (char**) malloc(splitCount * sizeof(char**));
for(i=0;i<splitCount;i++) {
splitCharPosition = indexOf(currentSubstring, splitChar);
substring(currentSubstring, target[i], 0, splitCharPosition);
currentLength = strlen(currentSubstring);
substring(currentSubstring, &currentSubstring, splitCharPosition + 1, curr entLength-splitCharPosition);
}
return splitCount;
}
The problem is that if I use the Debugger, the pointer to splitChar is set to 0x0 after the first run of the for loop.
Does anybody know why it is set to 0x0?
EDIT:
int indexOf(char* source, char* template) {
int i;
int j;
int index;
for (i = 0; source[i]; i++) {
index = i;
for (j = 0; template[j]; j++) {
if (source[i + j] != template[j]) {
index = -1;
break;
}
}
if (index != -1) {
return index;
}
}
return -1;
}
EDIT2:
int charcount(char* source, const char* countChar) {
int i;
int count = 0;
for(i=0;source[i];i++) {
if(source[i] == countChar[0]) {
count++;
}
}
return count;
}
EDIT3:
char* substring(char* source, char** target, int start, int length) {
*target = (char*) malloc(length + 1);
strncpy(*target, source + start, length);
target[length] = '\0';
return *target;
}
EDIT4:
I just noticed that if I add
char* sndfpgjps = splitChar;
to my split() code it does not delete the reference. Anyone know why?
This line:-
substring(currentSubstring, &currentSubstring, splitCharPosition + 1, curr entLength-splitCharPosition);
... will cause a memory leak, as well as being incredibly inefficient. The old substring is left dangling. and never freed.
It would be much better to write
currentSubString += splitCharPosition + 1;
I don't think that's the problem, but it's a problem.
Also, as you're using C library functions like strlen(), why aren't you using strtok or better yet, strtok_r?
I have some reservations about the code, but this works cleanly under valgrind (no leaks, no abuse). I've left the sub-functions largely unchanged except that constant strings are marked constant. The code in split() has been simplified. As I noted in a comment, I suggest writing the main split() function so that you have a local char **string_list; which you allocate and fill. Then, when you're about to return, you assign *target = string_list;. This will make it easier for you to understand what's going on. Triple indirection is nasty. You can justify it here (just), but minimize the time you spend working with triple pointers. The revision adopts that strategy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int split(const char *source, char ***target, const char *splitStr);
static int
indexOf(const char *source, const char *template)
{
int i;
int j;
int index;
for (i = 0; source[i]; i++)
{
index = i;
for (j = 0; template[j]; j++)
{
if (source[i + j] != template[j])
{
index = -1;
break;
}
}
if (index != -1)
return index;
}
return -1;
}
static int
charcount(const char *source, const char *countChar)
{
int count = 0;
for (int i = 0; source[i]; i++)
{
if (source[i] == countChar[0])
count++;
}
return count;
}
static char *
substring(const char *source, int start, int length)
{
char *target = (char *)malloc(length + 1);
if (target != 0)
{
memmove(target, source + start, length);
target[length] = '\0';
}
return target;
}
int
split(const char *source, char ***target, const char *splitStr)
{
int splitCount = charcount(source, splitStr) + 1;
char **result = (char **)malloc(splitCount * sizeof(*result));
if (result == 0)
return -1;
int splitLength = strlen(splitStr);
char **next = result;
const char *currentSubstring = source;
for (int i = 0; i < splitCount; i++)
{
int splitCharPosition = indexOf(currentSubstring, splitStr);
if (splitCharPosition < 0)
break;
*next++ = substring(currentSubstring, 0, splitCharPosition);
currentSubstring += splitCharPosition + splitLength;
}
*next++ = substring(currentSubstring, 0, strlen(currentSubstring));
*target = result;
return (next - result); /* Actual number of strings */
}
static void print_list(int nstrings, char **strings)
{
for (int i = 0; i < nstrings; i++)
{
if (strings[i] != 0)
printf("%d: <<%s>>\n", i, strings[i]);
}
}
static void free_list(int nstrings, char **strings)
{
for (int i = 0; i < nstrings; i++)
free(strings[i]);
free(strings);
}
int main(void)
{
const char source[] = "This is a string; it is really!";
char **strings;
int nstrings;
nstrings = split(source, &strings, " ");
printf("Splitting: <<%s>> on <<%s>>\n", source, " ");
print_list(nstrings, strings);
free_list(nstrings, strings);
nstrings = split(source, &strings, "is");
printf("Splitting: <<%s>> on <<%s>>\n", source, "is");
print_list(nstrings, strings);
free_list(nstrings, strings);
return 0;
}
Note that in the second example, charcount() returns 6 but there are only 4 strings. This caused a late adjustment to the source code. (You could realloc() the result so it is exactly the right size, but it probably isn't worth worrying about unless the discrepancy is really marked — say 'more than 10 entries'.) The error handling is not perfect; it doesn't access invalid memory after failure to allocate, but it doesn't stop trying to allocate, either. Nor does it report failures to allocate individual strings — it does for failure to allocate the array of pointers.
I'd probably avoid the triple pointer by creating a structure:
typedef struct StringList
{
size_t nstrings;
char **strings;
} StringList;
You can then pass a pointer to one of these into split(), and into the utility functions such as free_list() and print_list(). The free_list() function would then modify the structure so that both elements are zeroed after the data pointed at by the structure is freed.
I'd also be tempted to use a different implementation of indexOf():
int indexOf(const char *haystack, const char *needle)
{
const char *pos = strstr(haystack, needle);
if (pos != 0)
return (pos - haystack);
return -1;
}
I do not know what substring does, nor what signature it has, but in the line
substring(currentSubstring, target[i], 0, splitCharPosition);
target[i] is only defined for i==0. I believe you wanted to write
substring(currentSubstring, (*target)[i], 0, splitCharPosition);
See if your debugger also supports data breakpoints, i.e. break if some place in memory is modified. Then place one at the actual address of splitChar, and another at the address it points to. (Since you didn't specify whether the pointer is null or points to nil.) See where it breaks. It may be that it is a completely unrelated place; that would indicate a buffer overflow.
Also, you could make at least splitChar a pointer to const. You don't actually want to modify it, right? Better idea, make it a char, not a pointer, since its name suggests that there is only one character on which you split, not a string.
The first call to substring does not look correct:
substring(currentSubstring, target[i], 0, splitCharPosition);
I suspect it should be something like the following where it indexes the actual memory that was allocated:
substring(currentSubstring, &((*target)[i]), 0, splitCharPosition);
You first need to get the value that target points at (*target) and then index off of that and pass the address of that array location.

Resources