problem with malloc and pointer matrixes 
Author Message
 problem with malloc and pointer matrixes

Hi I have a problem with storing data read from an SQL database into a matix (char ***).
I allocate memory for all elements but after inserting the data it disapears and the
program crashes with a segmentation fault. I have done a test program using exactly
the same design and it works flawless. Maybe I'm doing something totaly wrong here in
my code, but I cant find anything.

/Bjorn

My SQL code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <mysql.h>

struct _table {
  char *tick;      
  char ***data;      

Quote:
} *table;

int
main(argc, argv)
  int argc;      
  char **argv;      
{
  MYSQL mysql;      
  MYSQL_RES *res;      
  MYSQL_ROW row;      
  void *query;      
  int i = 0, x = 0;

  table = malloc(256 * sizeof(struct _table));      

  mysql_init(&mysql);      
  if (!mysql_real_connect(&mysql, "localhost", "root", "password", "trendwatch", 0, NULL, 0))      
  {      
    fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&mysql));            
  }      

  if (mysql_query(&mysql, "SHOW TABLES"))      
  {      
    fprintf(stderr, "Failed to query database: Error: %s\n", mysql_error(&mysql));            
  }      
  else      
  {      
    res = mysql_store_result(&mysql);            
    while ((row = mysql_fetch_row(res)))            
      table[i++].tick = strdup(row[0]);                  
    mysql_free_result(res);            
  }      

  for (i=0 ; table[i].tick ; i++)      
  {      
    query = malloc(strlen("SELECT * FROM ") + strlen(table[i].tick) + 1);            
    sprintf(query, "%s %s", "SELECT * FROM", table[i].tick);            

    if (mysql_query(&mysql, query))            
    {            
      fprintf(stderr, "Failed to query database: Error: %s\n", mysql_error(&mysql));                  
    }            
    else            
    {            
      res = mysql_store_result(&mysql);                  
      x=0;                  
      while ((row = mysql_fetch_row(res)))                  
      {                  
        table[i].data = malloc(1000000);
        table[i].data[x] = malloc(1000000);
        table[i].data[x][0] = strdup(row[0]);
        printf("%d %s %s\n", i, table[i].tick, table[i].data[x][0]);
        x++;
      }
      mysql_free_result(res);
      printf("dump data: %s\n", table[0].data[0][0]); /* This is where it crashes */
    }
    free(query);

  }
  mysql_close(&mysql);

  printf("Content-type: text/plain\n\n");
  printf("testar 1 2 3\n");

  return 0;

Quote:
}

My test code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

struct _table {
  char ***ptr;      

Quote:
} *table;

int main(int argc,char **argv)
{
  int i, x, z;      
  table = malloc(sizeof(struct _table));      

  table[0].ptr = malloc(sizeof(char ***));      
  table[0].ptr[0] = malloc(sizeof(char **));      
  table[0].ptr[0][0] = strdup("table 0 row 0 col 0");      
  table[0].ptr[0][1] = strdup("table 0 row 0 col 1");      
  table[0].ptr[1] = malloc(sizeof(char **));      
  table[0].ptr[1][0] = strdup("table 0 row 1 col 0");      
  table[0].ptr[1][1] = strdup("table 0 row 1 col 1");      

  table[1].ptr = malloc(sizeof(char ***));      
  table[1].ptr[0] = malloc(sizeof(char **));      
  table[1].ptr[0][0] = strdup("table 1 row 0 col 0");      
  table[1].ptr[0][1] = strdup("table 1 row 0 col 1");      
  table[1].ptr[1] = malloc(sizeof(char **));      
  table[1].ptr[1][0] = strdup("table 1 row 1 col 0");      
  table[1].ptr[1][1] = strdup("table 1 row 1 col 1");      

  table[2].ptr = malloc(sizeof(char ***));      
  table[2].ptr[0] = malloc(sizeof(char **));      
  table[2].ptr[0][0] = strdup("table 2 row 0 col 0");      
  table[2].ptr[0][1] = strdup("table 2 row 0 col 1");      
  table[2].ptr[1] = malloc(sizeof(char **));      
  table[2].ptr[1][0] = strdup("table 2 row 1 col 0");      
  table[2].ptr[1][1] = strdup("table 2 row 1 col 1");      

  table[3].ptr = NULL;      

  for (i=0 ; table[i].ptr != NULL ; i++)      
    for (x=0 ; table[i].ptr[x] != NULL ; x++)            
      for (z=0 ; table[i].ptr[x][z] != NULL ; z++)                  
        printf("%s\n", table[i].ptr[x][z]);
  return 0;      

Quote:
}

~


Mon, 23 Sep 2002 03:00:00 GMT  
 problem with malloc and pointer matrixes


Quote:
> Hi I have a problem with storing data read from an SQL database into
a matix (char ***).
> I allocate memory for all elements but after inserting the data it
disapears and the
> program crashes with a segmentation fault. I have done a test program
using exactly
> the same design and it works flawless. Maybe I'm doing something

totaly wrong here in

Quote:
> my code, but I cant find anything.

[snippage]

I lifted some of your code to make a test program:
#includes...

struct _table
{
  char *tick;
  char ***data;

Quote:
} *table;

char * sample = "some data";

int main( void )
{
        int ix;

        table = malloc(256 * sizeof(struct _table));

/* populating *some* of the struct members */
        for (ix = 0 ; ix < 10 ; ix++)
                table[ix].tick = sample;

/* loop control as in original code. *tick is indeterminate.
   Here, I just print out the value of the pointer. */
        for (ix = 0 ; table[ix].tick ; ix++)
                printf( "table[%d]=%p\n", ix, table[ix] );

        return 0;

Quote:
}

Seems to me your loop control above is at least one of the problems.
Don't know about mysql. When I run this, I get various results,
including:

table[0]=0042001C
table[1]=0042001C
table[2]=0042001C
table[3]=0042001C
table[4]=0042001C
table[5]=0042001C
table[6]=0042001C
table[7]=0042001C
table[8]=0042001C
table[9]=0042001C
table[10]=CDCDCDCD <<< from here on, you're in uncharted territory
table[11]=CDCDCDCD
table[12]=CDCDCDCD
table[13]=CDCDCDCD
table[14]=CDCDCDCD
table[15]=CDCDCDCD
table[16]=CDCDCDCD
table[17]=CDCDCDCD
table[18]=CDCDCDCD
table[19]=CDCDCDCD
table[20]=FDFDFDFD
table[21]=000000D1
table[22]=00431E50
table[23]=00420BBC
table[24]=00000019
table[25]=0000002D
table[26]=49575857
table[27]=6365545C
table[28]=6E6F6874
table[29]=FDFDFD00

Sent via Deja.com http://www.deja.com/
Before you buy.



Mon, 23 Sep 2002 03:00:00 GMT  
 problem with malloc and pointer matrixes


:> Hi I have a problem with storing data read from an SQL database into
: a matix (char ***).
:> I allocate memory for all elements but after inserting the data it
: disapears and the
:> program crashes with a segmentation fault. I have done a test program
: using exactly
:> the same design and it works flawless. Maybe I'm doing something
: totaly wrong here in
:> my code, but I cant find anything.
:>

: [snippage]

: I lifted some of your code to make a test program:
: #includes...

Ok, but I found the problem, it was that I allocated the base array[0]
inside the while loop so the whole base array area was overwritten for
each row read form the SQL results object.
Now it works ok anyway. I must be blind to not notice this simple
misstake then I had it infront of my nose all the time. ;)

[0] table[0].data = malloc(100000);

/Bjorn



Mon, 23 Sep 2002 03:00:00 GMT  
 problem with malloc and pointer matrixes
(posted and mailed)

Quote:
> Hi I have a problem with storing data read from an SQL database into a
matix (char ***).
> I allocate memory for all elements but after inserting the data it
disapears and the
> program crashes with a segmentation fault. I have done a test program
using exactly
> the same design and it works flawless. Maybe I'm doing something totaly
wrong here in
> my code, but I cant find anything.

> /Bjorn

> My SQL code:

> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <string.h>
> #include <mysql.h>

> struct _table {
>   char *tick;
>   char ***data;
> } *table;

> int
> main(argc, argv)
>   int argc;
>   char **argv;
> {
>   MYSQL mysql;
>   MYSQL_RES *res;
>   MYSQL_ROW row;
>   void *query;
>   int i = 0, x = 0;

>   table = malloc(256 * sizeof(struct _table));

>   mysql_init(&mysql);
>   if (!mysql_real_connect(&mysql, "localhost", "root", "password",

"trendwatch", 0, NULL, 0))

Quote:

>     fprintf(stderr, "Failed to connect to database: Error: %s\n",

mysql_error(&mysql));
Quote:
>   }

If there was an error you probably want to exit (or return)
rather than continuing.

Quote:
>   if (mysql_query(&mysql, "SHOW TABLES"))

>     fprintf(stderr, "Failed to query database: Error: %s\n",

mysql_error(&mysql));

Quote:
>   }
>   else

>     res = mysql_store_result(&mysql);
>     while ((row = mysql_fetch_row(res)))
>       table[i++].tick = strdup(row[0]);
>     mysql_free_result(res);
>   }

That combination is valid only if MYSQL_ROW is actually char**
(possibly plus const's) (which is quite plausible).
If the number of tables listed is > 256 you run off the end
of your malloc'ed memory and clobber something;
should check for this and either stop or realloc 'table'.
Some RDBMSes allow you determine the size of the
result set, and allocate accordingly; I don't know about mysql.

strdup() is not standard C but I assume it is the usual
(and obvious) extension.  If the size of table names
is limited to some moderate size by your RDBMS
(as many do, again I don't know about mysql) or
can be (assumed) limited in your actual database,
you could just strcpy to a char array directly in table.

I would call a field containing the table name something
like tbl_name; 'tick' is not at all mnemonic to me.

Quote:
>   for (i=0 ; table[i].tick ; i++)

>     query = malloc(strlen("SELECT * FROM ") + strlen(table[i].tick) + 1);
>     sprintf(query, "%s %s", "SELECT * FROM", table[i].tick);

>     if (mysql_query(&mysql, query))

>       fprintf(stderr, "Failed to query database: Error: %s\n",

mysql_error(&mysql));

- Show quoted text -

Quote:
>     }
>     else

>       res = mysql_store_result(&mysql);
>       x=0;
>       while ((row = mysql_fetch_row(res)))

>         table[i].data = malloc(1000000);
>         table[i].data[x] = malloc(1000000);
>         table[i].data[x][0] = strdup(row[0]);
>         printf("%d %s %s\n", i, table[i].tick, table[i].data[x][0]);
>         x++;
>       }
>       mysql_free_result(res);
>       printf("dump data: %s\n", table[0].data[0][0]); /* This is where it
crashes */
>     }
>     free(query);

>   }
>   mysql_close(&mysql);

There is no guarantee that the table[].tick were initialized to null
by the malloc above, so this can run off the end and process
garbage (or fail in other unpredictable and damaging ways).
You want to loop to the previous value of i, which you might
more helpfully name something like num_of_tables.

Since query is actually being used to contain chars, I would
declare it as char* rather than void* (though that does work).
Moreover, if table names are bounded (as above) I would just
declare a local array of say 20+50 char, rather than malloc
and free each time -- primarily to simplify the source,
any minor gain in efficiency being gravy.

Your main problem is that you allocate a new (and different)
array-of-rowptr every time through the 'x' loop, so if you have
say 20 rows, after the last loop only .data[19] is validly set
(to the data for row #19) and 0..18 are garbage, while the
previous 19 allocations of .data each containing one valid ptr
are inaccessible, and leaked.

Allocating an arbitrary million bytes for .data and .data[x]
is silly.  The former should be num_of_rows * sizeof(char**)
or equivalently * sizeof * table[i].data, where num_of_rows
is either a limit, or the actual or estimated number so far
and you realloc when necessary to increase it.  Note that
you need parens around a typename but they are optional
around a reference to the target (or any other) object.
Similarly the latter should be sizeof(char*) or more generally
num_cols * sizeof (char*) or sizeof * table[i].data[x] .
num_cols should be the same for all rows and obtainable
before you begin fetching rows (the x loop) at latest;
it is on other RDBMSes.

You are implicitly assuming that each row contains only one
(significant) field, and that mysql has returned it as a C string.
I assume (hope) that this is just your simplified-for-posting
code and the real code is more general.

Quote:
>   printf("Content-type: text/plain\n\n");
>   printf("testar 1 2 3\n");

>   return 0;
> }

On a Unix-like system I expect this will generate only two
LF after the header line, not the two CR LF pairs required
for a valid HTTP header.  (LF alone is a valid EOL in the
HTML *body*, but not by standard in the header.)

- Show quoted text -

Quote:
> My test code:

> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <string.h>

> struct _table {
>   char ***ptr;
> } *table;

> int main(int argc,char **argv)
> {
>   int i, x, z;
>   table = malloc(sizeof(struct _table));

>   table[0].ptr = malloc(sizeof(char ***));
>   table[0].ptr[0] = malloc(sizeof(char **));
>   table[0].ptr[0][0] = strdup("table 0 row 0 col 0");
>   table[0].ptr[0][1] = strdup("table 0 row 0 col 1");
>   table[0].ptr[1] = malloc(sizeof(char **));
>   table[0].ptr[1][0] = strdup("table 0 row 1 col 0");
>   table[0].ptr[1][1] = strdup("table 0 row 1 col 1");

>   table[1].ptr = malloc(sizeof(char ***));
>   table[1].ptr[0] = malloc(sizeof(char **));
>   table[1].ptr[0][0] = strdup("table 1 row 0 col 0");
>   table[1].ptr[0][1] = strdup("table 1 row 0 col 1");
>   table[1].ptr[1] = malloc(sizeof(char **));
>   table[1].ptr[1][0] = strdup("table 1 row 1 col 0");
>   table[1].ptr[1][1] = strdup("table 1 row 1 col 1");

>   table[2].ptr = malloc(sizeof(char ***));
>   table[2].ptr[0] = malloc(sizeof(char **));
>   table[2].ptr[0][0] = strdup("table 2 row 0 col 0");
>   table[2].ptr[0][1] = strdup("table 2 row 0 col 1");
>   table[2].ptr[1] = malloc(sizeof(char **));
>   table[2].ptr[1][0] = strdup("table 2 row 1 col 0");
>   table[2].ptr[1][1] = strdup("table 2 row 1 col 1");

>   table[3].ptr = NULL;

>   for (i=0 ; table[i].ptr != NULL ; i++)
>     for (x=0 ; table[i].ptr[x] != NULL ; x++)
>       for (z=0 ; table[i].ptr[x][z] != NULL ; z++)
>         printf("%s\n", table[i].ptr[x][z]);
>   return 0;
> }

This version correctly assigns each table[].ptr once,
not for each 'x', and sets the first unused table[].ptr to null.
But the malloc for table needs to be 4 * sizeof *table,
and here you use .ptr[0:1] and .ptr[][0:1],
so those malloc's need to be for 2 * sizeof whatever,
or 3 * and set [2] to NULL to use the sentinel logic.

It shouldn't work unless you happen to be using a heapmgr
that rounds small allocations up to say 16 bytes
(which is perfectly legal and sometimes reasonable)
and either the allocated memory is zeroed or happens
to be already zero (the latter is usual on Unix, though not
guaranteed in all circumstances) and your machine
represents nullptr as all-zero-bits (very common though
not actually required; see FAQ section 5).

--
- David.Thompson 1 now at worldnet.att.net



Wed, 02 Oct 2002 03:00:00 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. How to use malloc() to allocate matrix

2. pointer & malloc problem

3. pointers and malloc problems

4. Q: problems allocating pointers with malloc

5. Struct & malloc problem : pointer expected

6. Some help with malloc pointer problems

7. malloc pointer problem !!

8. malloc/pointer problem

9. add and multiply matrices with pointer Arithmetic help.

10. pointer to matrix syntax

11. Pointers and matrices

12. Q: Matrixes and pointers

 

 
Powered by phpBB® Forum Software