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. :)
Related
Heyo,
I have problem allocating memory for my "database"
i have this struct
typedef struct TPrvek {
struct TPrvek *parent1;
struct TPrvek *parent2;
int id;//key
char *name;//value
} TPrvek;
typedef struct Database {
int size;
struct TPrvek **TField;
} DATABASE;
and I am initializing like this :
void init(DATABASE *db) {
DATABASE *newDb = (DATABASE *) malloc(sizeof(DATABASE));
newDb->size = 1000;//initial capacity
newDb->TField = (TPrvek **) calloc(newDb->size, sizeof(TPrvek *));
for (int i = 0; i < db->size; i++) {
newDb->TField[i] = NULL;
}
*db = *newDb;
}
But when i try to insert smth to it, im writing out of allocated memmory and I don't know how to repair it nor what is even wrong
snipet of insertion:
int addPerson(DATABASE *db,
int id,
const char *name,
int id1,
int id2) {
//some checks to make sure ids are in bounds and field for new person is empty
TPrvek *clovek = (TPrvek *) malloc(sizeof(TPrvek));
clovek->name = (char *) malloc(sizeof(name) + 1);
strcpy(clovek->name, name);
clovek->id = id;
//clovek->parent1 = (TPrvek *) malloc(sizeof(TPrvek));
//clovek->parent2 = (TPrvek *) malloc(sizeof(TPrvek));I was desperate, this is wrong I think
clovek->parent1 = db->TField[id1];
clovek->parent2 = db->TField[id2];
db->TField[id] = clovek;
//returns 1 if success
}
and in the main I have simple asserts to check functionality like :
int main(int argc,
char *argv[]) {
DATABASE a;
init(&a);
assert (addPerson(&a, 1, "John", 0, 0) == 1);
assert (addPerson(&a, 2, "Caroline", 0, 0) == 1);
...}
Any ideas?
I'm pretty new to c and memory allocating in general, so I would be glad for every bit of help :)
This line is the problem (at least one I see straight away):
clovek->name = (char *) malloc(sizeof(name) + 1);
Type of name is char *, and sizeof(char *) is size of pointer - always 8.
What you need instead is the length of string, i.e:
clovek->name = (char *) malloc(strlen(name) + 1);
I am working on a sqlite-.dll for educational purpose.
I am trying to dynamically add a row in my 2 dimensional array for each time the callback function is called with a new row from the database. (e.g. SELECT * FROM CUSTOMER).
The data stored in this array should then be returned as a C-Interface.
SQLCONTROL_API char** sql_execQuery(char *dbName, char *sqlStatement)
{
char **a = 0;
/*Some sqlite stuff*/
int rc = sqlite3_exec(db, sqlStatement, callback, &a, &zErrMsg);
return a;
}
With the callback function:
static int callback(void *data, int argc, char **argv, char **azColName)
{
char **old = (char **)data;
int num_rows = sizeof(old) / sizeof(old[0]);
int num_cols = sizeof(old[0]) / sizeof(old[0][0]);
old = (char **)realloc(old, (num_rows + 1) * sizeof(char *));
for (int i = 0; i < (num_rows + 1); i++)
old[i] = (char *)realloc(old[i], argc * sizeof(char *));
/*I am trying to create a 2 dim array that looks like a table,
so the column names are in the first row,
then the data from the table is stored in each row*/
for (int i = 0; i < argc; i++)
{
if (num_rows == 1)
old[0][i] = *azColName[i];
old[num_rows][i] = *argv[i];
}
data = old;
return 0;
}
When inserting data to the database, everything works fine. But when I try to retrieve data, I get read access violation.
Now my question, am I on the right way with my approach or do I miss some important requirements for my intention?
In your sql_execQuery(), you declare a as a char **, and you pass its address, &a, as the fourth argument of sqlite3_exec(). That argument therefore has type char ***, and it points to a location somewhere in the program's stack. There's nothing inherently wrong with that.
But then we get to callback(), which has serious problems, principal among them:
It treats the data pointer as if it were of type char **, instead of the correct type, char ***. If that were your only problem, you could fix it like this:
char **old = *(char ***)data;
// ...
*(char ***)data = old;
It tries to compute the dimensions of the allocated space via the sizeof operator, as would be reasonable if old were, in fact, a 2D array, but it is not an array at all. It is a pointer to pointer to char, so sizeof(old) is the size of a pointer (to pointer to char), sizeof(old[0]) is the size of a pointer (to char) and sizeof(old[0][0]) is the size of a char. This does not tell you anything about how much space has been allocated.
After allocating memory for old, it dereferences the parts of the allocated memory without initializing them, by passing them to realloc(). Generally, all but one of these will have been initialized, but the one uninitialized one causes realloc() to exhibit undefined behavior.
You fail to check for allocation errors.
It looks like you need a more complex data structure to be passed through to your callback, so that you can track the allocated dimensions. Something like this, for example:
struct mytable {
char **data;
size_t dim;
};
SQLCONTROL_API char** sql_execQuery(char *dbName, char *sqlStatement)
{
struct mytable a = { NULL, 0 };
// ...
int rc = sqlite3_exec(db, sqlStatement, callback, &a, &zErrMsg);
return a.data;
}
static int callback(void *data, int argc, char **argv, char **azColName)
{
struct mytable *old = data;
char **temp;
old->dim++;
temp = realloc(old->data, old->dim * sizeof(*old->data));
if (temp) {
old->data = temp;
old->data[old->dim - 1] = NULL;
} else {
// handle allocation error ...
}
for (int i = 0; i < old->dim; i++) {
char *temp2 = realloc(old->data[i], argc * sizeof(*old->data[i]));
if (temp2) {
old->data[i] = temp2;
old->data[i][argc - 1] = NULL;
} else {
// handle allocation error ...
}
}
// ... other stuff ...
// no need for anything like data = old
return 0;
}
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));
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).
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, ¤tSubstring, 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, ¤tSubstring, 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.