0

3D version of this array allocation seems to work fine, but adding a fourth dimension apparently causes a segfault. Edit: (Turns out the pointer stuff was fine, just a pair of typos in the inner loop)

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

    #define M 2
    #define N 3
    #define O 4
    #define P 5

    int main()
    {
        int ****A = malloc(sizeof(int***)*M);
        int i, j, k, m;

        if(!A) 
        {
            printf (" **** Out of Memory");
        }
        for(i = 0; i < M; i++)
        {
            A[i] = malloc(sizeof(int**)*N);
            if(!A[i]) 
            {
                 printf(" *** Out of Memory");
            }
            for(j = 0; j < N; j++)
            {
                A[i][j] = malloc(sizeof(int*)*O);
                if(!A[i][j]) 
                {
                    printf(" ** Out of Memory");
                }
                for(k = 0; k < O; k++)
                {

/* TYPO 1 - former site of main problem, a "==" typo */
                    A[i][j][k] = malloc(sizeof(int)*P); 
                    if(!A[i][j][k]) 
                    {
                        printf(" * Out of Memory\n");
                    }

/* TYPO 2 - former site of ")A;" typo unrelated to main problem */
                    printf("Allocation: A[i][j][k] at %p, A[i][j]: %p, A[i]: %p, A: %p\n", A[i][j][k], A[i][j], A[i], A); 
                }
            }
        }
        return 0;
    }

Mingw gives an out of memory error after 18 – 26 allocations, no matter what size goes in M, N, O, P.

Same code running on linux gcc produces errors and a segfault immediately

3-dimensional version of this code (just one less for-loop) works and doesn’t produce errors.

mingw output:

Allocation: A[i][j][k] at 00B326F8, A[i][j]: 00B30D60, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 00B300C0, A[i][j]: 00B30D60, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 69575C3A, A[i][j]: 00B30D60, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 776F646E, A[i][j]: 00B30D60, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 00B33700, A[i][j]: 00B30DF8, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 00B300C0, A[i][j]: 00B30DF8, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 45434F52, A[i][j]: 00B30DF8, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 524F5353, A[i][j]: 00B30DF8, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 00B33700, A[i][j]: 00B30E90, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 00B300C0, A[i][j]: 00B30E90, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 6F646E69, A[i][j]: 00B30E90, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 535C7377, A[i][j]: 00B30E90, A[i]: 00B30D48, A: 76FD74CD

Allocation: A[i][j][k] at 00B33700, A[i][j]: 00B30F40, A[i]: 00B30F28, A: 76FD74CD

Allocation: A[i][j][k] at 00B300C0, A[i][j]: 00B30F40, A[i]: 00B30F28, A: 76FD74CD

Allocation: A[i][j][k] at 6D766E44, A[i][j]: 00B30F40, A[i]: 00B30F28, A: 76FD74CD

Allocation: A[i][j][k] at 5C3A433B, A[i][j]: 00B30F40, A[i]: 00B30F28, A: 76FD74CD

Allocation: A[i][j][k] at 00B30FD8, A[i][j]: 00B304A0, A[i]: 00B30F28, A: 76FD74CD

Allocation: A[i][j][k] at 00B300C0, A[i][j]: 00B304A0, A[i]: 00B30F28, A: 76FD74CD

Allocation: A[i][j][k] at 00000231, A[i][j]: 00B304A0, A[i]: 00B30F28, A: 76FD74CD

 * Out of Memory

Allocation: A[i][j][k] at 00000000, A[i][j]: 00B304A0, A[i]: 00B30F28, A: 76FD74CD

Allocation: A[i][j][k] at 00B304D8, A[i][j]: 00B313E0, A[i]: 00B30F28, A: 
76FD74CD

Allocation: A[i][j][k] at 00B300C0, A[i][j]: 00B313E0, A[i]: 00B30F28, A: 76FD74CD

Allocation: A[i][j][k] at 6F646E69, A[i][j]: 00B313E0, A[i]: 00B30F28, A: 76FD74CD

Allocation: A[i][j][k] at 00007377, A[i][j]: 00B313E0, A[i]: 00B30F28, A: 76FD74CD

Process returned 255 (0xFF)   execution time : 3.891 s

On linux, identical code produces:

* Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617028, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617028, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617028, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617028, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x96170a0, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x96170a0, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x96170a0, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x96170a0, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617118, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617118, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617118, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617118, A[i]: 0x9617018, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x96171a0, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x96171a0, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x96171a0, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x96171a0, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617218, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617218, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617218, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617218, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617290, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617290, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617290, A[i]: 0x9617190, A: 0x24ab80

 * Out of Memory

Allocation: A[i][j][k] at (nil), A[i][j]: 0x9617290, A[i]: 0x9617190, A: 0x24ab80

Segmentation fault

Edit: It wasn't a pointer notation problem at all. Had a random "==" instead of "=" and a misplaced ")" in the print statement.

BitPass
  • 61
  • 7
  • 7
    `A[i][j][k] == (int*)malloc(sizeof(int)*P);`--> `A[i][j][k] =(int*)malloc(sizeof(int)*P);` – user2736738 Dec 29 '17 at 12:46
  • Voting to close as a typo. – Sergey Kalinichenko Dec 29 '17 at 12:47
  • 1
    `A[i]), A;` at the end of the print line... please turn on warnings on your compiler and fix them before posting here. – Mat Dec 29 '17 at 12:47
  • 3
    Do not cast the result of `malloc` in C. – Sergey Kalinichenko Dec 29 '17 at 12:48
  • 1
    Should this `A[i][j][k] == (int*)malloc(sizeof(int)*P);` result in a warning like `code has no effect`? – alk Dec 29 '17 at 12:50
  • 4
    Just so you know, if your compiler supports variable-length arrays, you can do `int (*A)[N][O][P] = malloc(M * sizeof(int [N][O][P]));` and get an actual four-dimensional array in one allocation instead of making multiple levels of pointers. – Eric Postpischil Dec 29 '17 at 12:53
  • @EricPostpischil: For the code given this even would work without VLA support. – alk Dec 29 '17 at 12:55
  • @alk.: Yes..but then this would also work `int A[M][N][O][P]` Why do even OP trying to allocate? Maybe someone asked OP to. – user2736738 Dec 29 '17 at 12:59
  • @coderredoc: Sure, but chances are good, it sooner or later would overflow the stack. – alk Dec 29 '17 at 13:00
  • I removed the " A[i]), A; " typo, however, the error was present before that line was written. Same error remains. – BitPass Dec 29 '17 at 13:15
  • @BitPass.: What error compiler shows? – user2736738 Dec 29 '17 at 13:18
  • @alk: Yes, if `M`, `N`, `O`, and `P` are all preprocessor macros expanding to constant expressions, then the array sizes are fixed at compile time, and the allocation can be performed in any C compiler. In case OP’s code in the question is just a sample, and the real or ultimate code will use run-time variables, variable-length array support would be needed. – Eric Postpischil Dec 29 '17 at 13:24
  • @EricPostpischil.: I have also been mentioning one thing ..if you use a VLA then it;s allocated in stack(if in the implenetation) but what you showed allocates from heap..though it involves VLA.? – user2736738 Dec 29 '17 at 13:26
  • on linux, segmentation fault, on windows, Unhandled exception at 0x77146BD3 (ntdll.dll) in array4Dimensional.exe: 0xC0000005: Access violation writing location 0x0000003E. – BitPass Dec 29 '17 at 13:28
  • @BitPass.: Check the code...try to understand it and check where you went wrong. – user2736738 Dec 29 '17 at 13:34
  • Why not just malloc a one dimension array doing the product of each dimension and then access it directly with `[][][][]` ? – Ôrel Dec 29 '17 at 13:39
  • @BitPass.: Have you checked the posted code...it works fine for me. Would you caliryfy what error you get? – user2736738 Dec 29 '17 at 13:49
  • @BitPass: The reason your code fails is because you accidentally wrote `==` instead of `=` in one of your statements. As a result, the statement only compares instead of assigns, so `A[i][j][k]` is never assigned a value. – Eric Postpischil Dec 29 '17 at 13:57
  • @codderredoc *facepalm* I missed it even when I read it as a comment. My brain is fried. It's the "==" thing. Thanks coderrec and thanks Eric – BitPass Dec 29 '17 at 13:58
  • Did you fix this `printf(..., A[i]), A;` as well? – alk Dec 29 '17 at 13:58
  • @coderredoc: Whether stack or heap is used has nothing to do with variable-length arrays. If you use `malloc`, the space is dynamically allocated (called “allocated storage duration” in the C standard). If you define an object inside a function and it is not static, the storage is “automatic.” Typically, the stack is used for objects with automatic storage duration, and something that some people call a “heap” (it is not necessarily a true [heap](https://en.wikipedia.org/wiki/Heap_(data_structure)) is used for allocated objects. But C implementations may accomplish these in other ways. – Eric Postpischil Dec 29 '17 at 14:01
  • @EricPostpischil.: Well yes..that's right. Standard doesn;t say anything about heap or stack. Yes I get it. Thanks. (Infact thats why I said if implementation allows heap or stack - never said that it is manadatory to have one ) – user2736738 Dec 29 '17 at 14:02
  • @BitPass: “failing” is not a proper problem report. If you still a have a problem besides the `==` instead of `=`, then you should report what behavior you observe and what behavior you expect, along with any changes in the code made since posting it in the question. – Eric Postpischil Dec 29 '17 at 14:03
  • @EricPostpischil, yep everything works now. I had two typos, one introduced in the test. Time to call it a night. – BitPass Dec 29 '17 at 14:32

1 Answers1

5
A[i][j][k] == (int*)malloc(sizeof(int)*P);

And then you try to access it

if(!A[i][j][k])

Giving you segmentation fault.

This worked for 3 dimension? Nope. Maybe because you didn't have this loop then.

Correction will be

A[i][j][k] = malloc(sizeof(int)*P);

You don't need that casting - it's redundant.

Also all these 4 mallocs can be much cleaner and hasslefree if you do this

int ****A = malloc(sizeof *A * M);

and

A[i] = malloc(sizeof *A[i] * N);

Also compile your code like this

gcc -Wall -Werror progname.c

This will throw an warning making you aware of this equality - equal problem.

Illustration code:-

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

#define M 2
#define N 3
#define O 4
#define P 5

int main(void)
{
    int ****A = malloc(sizeof*A*M);


    if(!A)
    {
        perror(" *** Out of Memory");
        exit(EXIT_FAILURE);
    }
    for(size_t i = 0; i < M; i++)
    {
        A[i] = malloc(sizeof *A[i]*N);
        if(!A[i])
        {
            perror(" *** Out of Memory");
            exit(EXIT_FAILURE);
        }
        for(size_t j = 0; j < N; j++)
        {
            A[i][j] = malloc(sizeof(int*)*O);
            if(!A[i][j])
            {
                perror(" *** Out of Memory");
                exit(EXIT_FAILURE);
            }
            for(size_t k = 0; k < O; k++)
            {
                A[i][j][k] = malloc(sizeof *A[i][j][k]*P);
                if(!A[i][j][k])
                {
                    perror(" *** Out of Memory");
                    exit(EXIT_FAILURE);
                }
                printf("Allocation: A[i][j][k] at %p, A[i][j]: %p, A[i]: %p, A: %p\n", (void*)A[i][j][k], (void*)A[i][j], (void*)A[i], (void*)A);
            }
        }
    }
    return 0;
}
user2736738
  • 30,591
  • 5
  • 42
  • 56
  • Version 2 (triple pointer) on this page does the same thing http://www.techiedelight.com/dynamically-allocate-memory-for-3d-array/ It's not the nicest syntax out there but I'm just experimenting with the limits of pointer notation. – BitPass Dec 29 '17 at 13:02
  • @BitPass.: You rarely need 3*** allocation. Don't follow random posts rather buy a book – user2736738 Dec 29 '17 at 13:04
  • Specific book recommendations? – BitPass Dec 29 '17 at 13:05
  • 1
    @BitPass.: https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list – user2736738 Dec 29 '17 at 13:06
  • 1
    Yeah I agree that "three-star" stuff is rarely needed in everyday code, but compilers for no-star languages are apparently full of them. – BitPass Dec 29 '17 at 13:09