LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   free freeing data twice or data that shoulnd't be freed (https://www.linuxquestions.org/questions/programming-9/free-freeing-data-twice-or-data-that-shoulndt-be-freed-4175430177/)

errigour 10-02-2012 07:26 PM

free freeing data twice or data that shoulnd't be freed
 
Maybe I'm declaring top->desc wrong but where I don't see it


Code:

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

struct areas
{
    int width;                    /* Area's map width                    */
    int height;                  /* Area's map height                    */

    char *name;                  /* Area's Name                          */
    char *descr;                  /* Area's Description                  */

    struct areas *next;          /* Structure for accessing all areas    */
};

int main()
{
    FILE *fp;

    struct areas *top;
    struct areas *next;

    short int x, y, width = 0, height = 0;
    char *ch;
    char name[100] = "NULL";
    char desc[10000] = "NULL";

    short int start = 0;

    ch = malloc(1);
    ch[1] = '\0';

    if ((fp = fopen(".hometown.map", "r")) == NULL)
          printf("Error opening hometown.map\r\n");

    fgets(name, 100, fp);
    name[strlen(name) - 1] = 0x00;

    for ( y = 0; ; y++)
    {
          if ( start == 1)
              height++;
          for ( x = 0; *ch != '\n'; x++)
          {
              fread(ch, 1, 1, fp);

              if(feof(fp)) { x = -1; width--; break;}

              if ( *ch == '~' ) start = 1;
              if ( height == 1) width++;

              printf("%c", ch[0]);
          }
          *ch = 0x00;
          if ( x == -1) break;
    }
    free(ch);
    fclose(fp);

    top = malloc(sizeof(top));

    top->width = width;
    top->height = height;

    top->name = malloc(strlen(name) + 1);
    strncpy(top->name, name, strlen(name));
    top->name[strlen(name) + 1] = 0x00;

    top->descr = malloc(strlen(desc) + 1);
    strncpy(top->descr, desc, strlen(desc));
    top->descr[strlen(desc) + 1] = 0x00;

    printf("\r\n");
    printf("top->width = %d\r\n", top->width);
    printf("top->height = %d\r\n", top->height);
    printf("top->name = %s\r\n", top->name);
    printf("top->description = %s\r\n", top->descr);
    printf("length of name: %d\r\n", strlen(name));
    printf("length of desc: %d\r\n", strlen(desc));
    free(top->descr);
    printf("descr freed\r\n");
    free(top->name);
    printf("name freed\r\n");
    free(top);
    printf("top freed\r\n");
}



---------- Post added 10-02-12 at 08:26 PM ----------

on this topic anyone know of a better debugger for linux?

---------- Post added 10-02-12 at 08:27 PM ----------

or how to debug this problem better?

ntubski 10-02-2012 07:58 PM

Code:

    ch = malloc(1);
    ch[1] = '\0';

You're writing past the end there.

Quote:

how to debug this problem better?
valgrind is often helpful for this kind of thing.

errigour 10-02-2012 08:21 PM

still crashing

errigour 10-02-2012 08:30 PM

also if you add top->next = NULL;

after line

top->descr[strlen(desc) + 1] = 0x00;

top->name equals nothing. wierd.

now it seems to be when freeing name

firstfire 10-02-2012 11:44 PM

Hi.

Let's debug your program using valgrind.
Code:

$ gcc -g crash.c  && valgrind ./a.out
crash.c: In function ‘main’:
crash.c:78:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
crash.c:79:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
==5524== Memcheck, a memory error detector
==5524== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5524== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5524== Command: ./a.out
==5524==
==5524== Invalid write of size 1
==5524==    at 0x40091E: main (crash.c:31)
==5524==  Address 0x51f1041 is 0 bytes after a block of size 1 alloc'd
==5524==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5524==    by 0x40090B: main (crash.c:30)
==5524==
==5524== Invalid read of size 4
==5524==    at 0x4EA10EE: fgets (iofgets.c:52)
==5524==    by 0x400968: main (crash.c:36)
==5524==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==5524==
==5524==
==5524== Process terminating with default action of signal 11 (SIGSEGV)
==5524==  Access not within mapped region at address 0x0
==5524==    at 0x4EA10EE: fgets (iofgets.c:52)
==5524==    by 0x400968: main (crash.c:36)
==5524==  If you believe this happened as a result of a stack
==5524==  overflow in your program's main thread (unlikely but
==5524==  possible), you can try to increase the size of the
==5524==  main thread stack using the --main-stacksize= flag.
==5524==  The main thread stack size used in this run was 8388608.
Error opening hometown.map
==5524==
==5524== HEAP SUMMARY:
==5524==    in use at exit: 1 bytes in 1 blocks
==5524==  total heap usage: 2 allocs, 1 frees, 569 bytes allocated
==5524==
==5524== LEAK SUMMARY:
==5524==    definitely lost: 0 bytes in 0 blocks
==5524==    indirectly lost: 0 bytes in 0 blocks
==5524==      possibly lost: 0 bytes in 0 blocks
==5524==    still reachable: 1 bytes in 1 blocks
==5524==        suppressed: 0 bytes in 0 blocks
==5524== Rerun with --leak-check=full to see details of leaked memory
==5524==
==5524== For counts of detected and suppressed errors, rerun with: -v
==5524== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)

Okay, we have invalid write on line 31:
Code:

    ch = malloc(1);
    ch[1] = '\0';    // line 31

This bug has already been discovered by ntubski. And we will see that the same error occurs two more times in the program. You allocated only one byte for ch, but on the next line (N31) you try to assign zero value to the second element of string ch. C uses zero-based indexing: first element has index 0, second element -- 1 etc. So to fix this bug you should write
Code:

    ch = malloc(1);
    ch[0] = '\0';    // line 31

(BTW why you use one-character dynamic string here instead of just char ch;?)
Fixed.

Repeat the procedure:
Code:

$ gcc -g crash.c  && valgrind ./a.out
crash.c: In function ‘main’:
crash.c:78:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
crash.c:79:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
==5568== Memcheck, a memory error detector
==5568== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5568== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5568== Command: ./a.out
==5568==
==5568== Invalid read of size 4
==5568==    at 0x4EA10EE: fgets (iofgets.c:52)
==5568==    by 0x400964: main (crash.c:36)
==5568==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==5568==
==5568==
==5568== Process terminating with default action of signal 11 (SIGSEGV)
==5568==  Access not within mapped region at address 0x0
==5568==    at 0x4EA10EE: fgets (iofgets.c:52)
==5568==    by 0x400964: main (crash.c:36)
==5568==  If you believe this happened as a result of a stack
==5568==  overflow in your program's main thread (unlikely but
==5568==  possible), you can try to increase the size of the
==5568==  main thread stack using the --main-stacksize= flag.
==5568==  The main thread stack size used in this run was 8388608.
Error opening hometown.map
==5568==
==5568== HEAP SUMMARY:
==5568==    in use at exit: 1 bytes in 1 blocks
==5568==  total heap usage: 2 allocs, 1 frees, 569 bytes allocated
==5568==
==5568== LEAK SUMMARY:
==5568==    definitely lost: 0 bytes in 0 blocks
==5568==    indirectly lost: 0 bytes in 0 blocks
==5568==      possibly lost: 0 bytes in 0 blocks
==5568==    still reachable: 1 bytes in 1 blocks
==5568==        suppressed: 0 bytes in 0 blocks
==5568== Rerun with --leak-check=full to see details of leaked memory
==5568==
==5568== For counts of detected and suppressed errors, rerun with: -v
==5568== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)

What's wrong with line 36:
Code:

    fgets(name, 100, fp);
? Looks good. But couple of lines above we see
Code:

    if ((fp = fopen(".hometown.map", "r")) == NULL)
          printf("Error opening hometown.map\r\n");

And we also see your error message "Error opening hometown.map". There are no such file as ".hometown.map" in my /tmp directory, naturally. The program tells us that there are no such file and just continues execution! Not good!
Code:

    if ((fp = fopen(".hometown.map", "r")) == NULL) {
          printf("Error opening hometown.map\r\n");
          free(ch); // to calm down valgrind
          exit(EXIT_FAILURE);
    }

Fixed.
Continue:
Code:

$ touch .hometown.map
$ gcc -g crash.c  && valgrind ./a.out
crash.c: In function ‘main’:
crash.c:81:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
crash.c:82:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
==5610== Memcheck, a memory error detector
==5610== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5610== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5610== Command: ./a.out
==5610==
==5610== Invalid write of size 8
==5610==    at 0x400B72: main (crash.c:68)
==5610==  Address 0x51f1318 is 0 bytes after a block of size 8 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid read of size 8
==5610==    at 0x400BAE: main (crash.c:69)
==5610==  Address 0x51f1318 is 0 bytes after a block of size 8 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid read of size 8
==5610==    at 0x400BC4: main (crash.c:70)
==5610==  Address 0x51f1318 is 0 bytes after a block of size 8 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid write of size 1
==5610==    at 0x400BFC: main (crash.c:70)
==5610==  Address 0x51f1364 is 0 bytes after a block of size 4 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B67: main (crash.c:68)
==5610==
==5610== Invalid write of size 8
==5610==    at 0x400C45: main (crash.c:72)
==5610==  Address 0x51f1320 is 8 bytes after a block of size 8 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid read of size 8
==5610==    at 0x400C87: main (crash.c:73)
==5610==  Address 0x51f1320 is 8 bytes after a block of size 8 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid read of size 8
==5610==    at 0x400C9D: main (crash.c:74)
==5610==  Address 0x51f1320 is 8 bytes after a block of size 8 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid write of size 1
==5610==    at 0x400CD8: main (crash.c:74)
==5610==  Address 0x51f13b5 is 0 bytes after a block of size 5 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400C3A: main (crash.c:72)
==5610==
==5610== Invalid read of size 8
==5610==    at 0x400D27: main (crash.c:79)
==5610==  Address 0x51f1318 is 0 bytes after a block of size 8 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B06: main (crash.c:63)
==5610==
==5610== Conditional jump or move depends on uninitialised value(s)
==5610==    at 0x4E7D3D1: vfprintf (vfprintf.c:1630)
==5610==    by 0x4E858F8: printf (printf.c:35)
==5610==    by 0x400D3F: main (crash.c:79)
==5610==
==5610== Invalid read of size 8
==5610==    at 0x400D47: main (crash.c:80)
==5610==  Address 0x51f1320 is 8 bytes after a block of size 8 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B06: main (crash.c:63)
==5610==
==5610== Conditional jump or move depends on uninitialised value(s)
==5610==    at 0x4E7D3D1: vfprintf (vfprintf.c:1630)
==5610==    by 0x4E858F8: printf (printf.c:35)
==5610==    by 0x400D5F: main (crash.c:80)
==5610==
==5610== Invalid read of size 8
==5610==    at 0x400DEE: main (crash.c:83)
==5610==  Address 0x51f1320 is 8 bytes after a block of size 8 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B06: main (crash.c:63)
==5610==
==5610== Invalid read of size 8
==5610==    at 0x400E0B: main (crash.c:85)
==5610==  Address 0x51f1318 is 0 bytes after a block of size 8 alloc'd
==5610==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5610==    by 0x400B06: main (crash.c:63)
==5610==

top->width = -1
top->height = 0
top->name = NUL
top->description = NULL
length of name: 3
length of desc: 4
descr freed
name freed
top freed
==5610==
==5610== HEAP SUMMARY:
==5610==    in use at exit: 0 bytes in 0 blocks
==5610==  total heap usage: 5 allocs, 5 frees, 586 bytes allocated
==5610==
==5610== All heap blocks were freed -- no leaks are possible
==5610==
==5610== For counts of detected and suppressed errors, rerun with: -v
==5610== Use --track-origins=yes to see where uninitialised values come from
==5610== ERROR SUMMARY: 14 errors from 14 contexts (suppressed: 2 from 2)

Oh no, not again..
Line 68:
Code:

    top->name = malloc(strlen(name) + 1);
Can we write to top->name? Did we allocated space for it?
Code:

    top = malloc(sizeof(top));
Hmm.. Yes? NO! What is top?
Code:

    struct areas *top;
It is a pointer, its size is something like 4 or 8 bytes. Hardly enough.. One should write
Code:

    top = malloc(sizeof(struct areas));
Fixed.

Continue:
Code:

$ gcc -g crash.c  && valgrind ./a.out
crash.c: In function ‘main’:
crash.c:81:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
crash.c:82:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
==5866== Memcheck, a memory error detector
==5866== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5866== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5866== Command: ./a.out
==5866==
==5866== Invalid write of size 1
==5866==    at 0x400BFC: main (crash.c:70)
==5866==  Address 0x51f1374 is 0 bytes after a block of size 4 alloc'd
==5866==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5866==    by 0x400B67: main (crash.c:68)
==5866==
==5866== Invalid write of size 1
==5866==    at 0x400CD8: main (crash.c:74)
==5866==  Address 0x51f13c5 is 0 bytes after a block of size 5 alloc'd
==5866==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5866==    by 0x400C3A: main (crash.c:72)
==5866==
==5866== Conditional jump or move depends on uninitialised value(s)
==5866==    at 0x4E7D3D1: vfprintf (vfprintf.c:1630)
==5866==    by 0x4E858F8: printf (printf.c:35)
==5866==    by 0x400D3F: main (crash.c:79)
==5866==
==5866== Conditional jump or move depends on uninitialised value(s)
==5866==    at 0x4E7D3D1: vfprintf (vfprintf.c:1630)
==5866==    by 0x4E858F8: printf (printf.c:35)
==5866==    by 0x400D5F: main (crash.c:80)
==5866==

top->width = -1
top->height = 0
top->name = NUL
top->description = NULL
length of name: 3
length of desc: 4
descr freed
name freed
top freed
==5866==
==5866== HEAP SUMMARY:
==5866==    in use at exit: 0 bytes in 0 blocks
==5866==  total heap usage: 5 allocs, 5 frees, 610 bytes allocated
==5866==
==5866== All heap blocks were freed -- no leaks are possible
==5866==
==5866== For counts of detected and suppressed errors, rerun with: -v
==5866== Use --track-origins=yes to see where uninitialised values come from
==5866== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 2 from 2)

Invalid writes on lines 70, 74:
Code:

    top->name = malloc(strlen(name) + 1);
    strncpy(top->name, name, strlen(name));
    top->name[strlen(name) + 1] = 0x00;        // line 70

    top->descr = malloc(strlen(desc) + 1);
    strncpy(top->descr, desc, strlen(desc));
    top->descr[strlen(desc) + 1] = 0x00;        // line 74

Again, you allocate array of strlen(name)+1 bytes and write to the last element, which should be (srtlen(name)+1)-1 = strlen(name):
Code:

    top->name = malloc(strlen(name) + 1);
    strncpy(top->name, name, strlen(name));
    top->name[strlen(name) ] = 0x00;        // line 70

    top->descr = malloc(strlen(desc) + 1);
    strncpy(top->descr, desc, strlen(desc));
    top->descr[strlen(desc) ] = 0x00;        // line 74

Fixed:
Code:

$ gcc -g crash.c  && valgrind ./a.out
crash.c: In function ‘main’:
crash.c:81:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
crash.c:82:6: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘size_t’ [-Wformat]
==5915== Memcheck, a memory error detector
==5915== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5915== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5915== Command: ./a.out
==5915==

top->width = -1
top->height = 0
top->name = NUL
top->description = NULL
length of name: 3
length of desc: 4
descr freed
name freed
top freed
==5915==
==5915== HEAP SUMMARY:
==5915==    in use at exit: 0 bytes in 0 blocks
==5915==  total heap usage: 5 allocs, 5 frees, 610 bytes allocated
==5915==
==5915== All heap blocks were freed -- no leaks are possible
==5915==
==5915== For counts of detected and suppressed errors, rerun with: -v
==5915== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

Hurrah!

errigour 10-03-2012 01:30 AM

I'm sorry I didn't include .hometown.map I thought I gave you everything you needed to debug and I myself
came up short. I must say I am much oblidged to you, Firstfire. top = malloc(sizeof(struct areas));
was exactly the problem. everything else is actually really cool.

Again thanks to Firstfire. I read it fifteen times and fifteen times I missed it.
And special thanks to Ntubski for pointing out my character.
Sharing my Cool skeleton project:
http://o0oo0.net16.net/shared

ch is a pointer cause fread doesn't like plain characters for some reason.
heres .hometown.map
http://o0oo0.net16.net/shared/.hometown.map

pan64 10-03-2012 02:27 AM

errigour, if you really think that post was helpful, please click on the "Yes" (bottom right corner). Firstfire made a very good job.

ntubski 10-03-2012 07:40 AM

Quote:

Originally Posted by errigour (Post 4795697)
ch is a pointer cause fread doesn't like plain characters for some reason.

fread() wants an address to write to, you can use the address-of operator, &:
Code:

char ch;
fread(&ch, 1, 1, fp);

Although if you're reading a single character it's easier to use getc():
Code:

int ch; /* getc returns a character or EOF so you need to use an int */
ch = getc(fp);

Oh, and regarding the malloc() for top, you can also use:
Code:

top = malloc(sizeof(*top));

bigearsbilly 10-04-2012 03:26 AM

I can't figure out what you are doing, linked-listing?
I think you are making life very difficult for yourself.

Why are you poncing about with malloc may I ask?
It's a recipe for mistakes avoid if you can.

If you must you can use strdup(3) to copy strings.

If it's a fire-and-forget application don't even waste your time calling free
the OS will recover any allocated space when you exit.

And don't do everything in one main function unless it's very trivial.
And I wouldn't use fread if I can get away with using stdio.h
(Let the OS do the work where you can and use your time for the interesting stuff).

ddd is a good front end for gdb.

errigour 10-04-2012 09:34 AM

well im using malloc because I can't get everything to compile right. I'm being difficult intentionally to master what I cannot do casually.

since you mention ddd maybe you can help me use it.
My program seems to be changing the address of char name[0] to 0x00. or I think because strlen of name = 0;
so how can I use ddd valgrind and gdb to find where the registry error is easily if I can. maybe you could show me an example use of ddd for this.

errigour 10-04-2012 11:45 AM

char area_map[10000][10000];
crashes my program
but when its not there the program runs great

johnsfine 10-04-2012 11:57 AM

Quote:

Originally Posted by errigour (Post 4797242)
char area_map[10000][10000];
crashes my program
but when its not there the program runs great

If you search for other threads on "stack size" I'm sure you can easily find both an explanation of the cause of the crash, and several alternatives for making it work.

One example is:
http://www.linuxquestions.org/questi...2/#post4688720

In the example in that post it is important that the call to increase the stack limit happens before the call to the function that includes the declaration of the large array. I think C99 allows you to declare the large array within a function after doing work, such as increasing the stack limit, earlier in the same function. That might work. With certain added tricks specific to C99, it could work reliably. But in most cases the compiler will move the stack allocation to the beginning of the function, so changing the limit earlier in the same function is not good enough. It needs to be changed in a different function executed before this function is called.

I expect you want that array declared in main() in some program similar to the one at the top of this thread. In C, that makes it very hard to execute code before the function is called. There are other methods, but I suggest you have too much code in main anyway. Consider moving almost everything from main to some other function called by main. I would tend to leave inside main certain steps like opening of required files (".hometown.map") and aborting if those files are missing, then pass the file pointer to the function that takes over most of main's previous job.

errigour 10-04-2012 01:28 PM

.hometown.map:
http://o0oo0.net16.net/shared/.hometown.map

Can I ask one more thing here instead of posting:
Code:

    top->area_map = calloc(height, width);
    for( y = 0; y < height; y++)
          for ( x = 0; x < width; x++)
          {
              printf("x: %d, y: %d\r\n", x, y);
              top->area_map[y][x] = area_map[y][x];
          }

the code above height is 501 width is 1001.
top->area_map is
char **area_map

is that a stack problem or am I defining it wrong?
i really gotta know how to do this thanks.

errigour 10-04-2012 01:34 PM

char area_map[500][1000]
it gives a segmentation fault at
top->area_map[0][0] = area_map[0][0];

johnsfine 10-04-2012 01:45 PM

Quote:

Originally Posted by errigour (Post 4797344)
Code:

    top->area_map = calloc(height, width);
...
              top->area_map[y][x] = area_map[y][x];

top->area_map is
char **area_map

is that a stack problem or am I defining it wrong?

You are defining it wrong (or allocating it wrong). It is not a stack problem.

char **area_map together with area_map[y][x] implies area_map points to a vector of pointers and each of those points to a separately allocated vector of data. You could replace the single allocation step with multiple allocations to build up the space implied by your current declaration and access code. Alternately, you could change the declaration to fit your existing allocation and access:

I think that would be:
Code:

typedef char data_row[1001];
struct areas {
...
data_row* area_map;
... };

In ANSI C, that method only works when the width is know at compile time (the height can still be decided at run time). The multi layered allocation lets both width and height be decided at run time. I think C99 and/or some gcc extension lets you use the declaration I suggested and still replace the 1001 with a variable. But I don't program in C99, so I might be confused on that detail.

errigour 10-04-2012 01:52 PM

what do I do?

johnsfine 10-04-2012 02:02 PM

Quote:

Originally Posted by errigour (Post 4797374)
what do I do?

I was editing some extra details into my above post while you replied, so maybe it answers that now even if it didn't when you first read it.

errigour 10-04-2012 02:16 PM

doesn't matter I found the answer thanks for all the help.

errigour 10-04-2012 02:25 PM

Here's the answer i think might be off by one:
Code:

struct areas
{
    char **area_map;
};
    struct areas *top;
    top = malloc(sizeof(areas));
    top->area_map = malloc(height);
    for( y = 0; y < height; y++)
    {
          top->area_map[y] = malloc(width);
          for ( x = 0; x < width; x++)
          {
              printf("y: %d, x: %d", y, x);
              top->area_map[y][x] = area_map[y][x];
          }
    }


johnsfine 10-04-2012 02:27 PM

Quote:

Originally Posted by errigour (Post 4797410)
Code:

    top->area_map = malloc(height);

Change that to
Code:

    top->area_map = malloc(height * sizeof(char*));

errigour 10-04-2012 05:39 PM

Got another multi demension array newb question:
I'm guessing because my program wont let me define the top elements of an array(not sure if my math is
wrong). Do I have to declare one extra number in both the height and the width of my area_map array?

just talkin about the local array not the structure.

errigour 10-04-2012 05:50 PM

It works like that im gonna leave it like that I just need some kind of reassurance that its breaking because
of that is all thanks alot.

errigour 10-04-2012 06:00 PM

also does allocating memory use ram or does it use hard disk space?

johnsfine 10-04-2012 07:00 PM

Quote:

Originally Posted by errigour (Post 4797563)
Do I have to declare one extra number in both the height and the width of my area_map array?

An array of size N has valid indexes from 0 through N-1 inclusive. Index N is not a valid index of an array of size N.

johnsfine 10-04-2012 07:04 PM

Quote:

Originally Posted by errigour (Post 4797576)
also does allocating memory use ram or does it use hard disk space?

Not exactly.

If you allocate a lot of memory, that just uses virtual address space (in "demand zero" mode). It doesn't use ram nor hard disk.

As you write to each page (aligned 4KB portion) of the allocated space, that page is forced to exist in ram. If you are short of ram, then forcing some page to exist in ram may push some other page (maybe part of the same allocation) out to swap space. If you are also short of swap space then it may force the OS to kill some process.

errigour 10-04-2012 07:10 PM

what about my maximum ram I only have 512 when will my program cease?

errigour 10-04-2012 07:11 PM

also that means I have to declare 1000 extra bytes just to have an array. seems kinda dumb.

johnsfine 10-04-2012 07:29 PM

Quote:

Originally Posted by errigour (Post 4797613)
also that means I have to declare 1000 extra bytes just to have an array. seems kinda dumb.

You seem to be missing the point. Think about an array
char[3][3];
Code:

  0 1 2
0 a b c
1 d e f
2 g h i

I showed indexes in blue and showed possible contents a .. i. There is no "extra". A 3x3 array has nine elements and you can use all nine. You can't use index 3, because the starting index is 0.

Quote:

Originally Posted by errigour (Post 4797613)
also that means I have to declare 1000 extra bytes just to have an array. seems kinda dumb.

Or maybe you meant the multi-level allocation to allow the char** declaration to be correct. For a 500x1000 array, that multi-level allocation costs a lot more than 1000 extra bytes. Each allocation has overhead, plus the pointers are it least 4 bytes each.

If you worry about that overhead, use the alternate declaration that allows you to malloc a single chunk.

But at 500x1000, these details don't matter. That is 500KB of data plus about 6KB of overhead. That is one tenth of one percent of your total ram.

Quote:

Originally Posted by errigour (Post 4797242)
char area_map[10000][10000];

But that is 100MB. That is a big enough fraction of your ram to take seriously, especially to ask why you want to have one version of that on the stack apparently just to copy it to another version allocated differently.

Quote:

Originally Posted by errigour (Post 4797610)
what about my maximum ram I only have 512 when will my program cease?

Assuming you have a decent size hard drive, I suggest you allocate a few (2 or 3) GB of swap space, so that when your program uses too much memory it will just get very slow rather than crash. That should make such problems easier to diagnose, quantify and correct.

errigour 10-04-2012 08:11 PM

Thankyou
SOLVED


All times are GMT -5. The time now is 12:18 AM.