0

i have a problem with the initialization of the values inside the first dynamic array of pointers

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char*** GetIndexes()
{
int n = 0;
char ***index;
printf("please insert the number of words you want to add to dictionary\n");
scanf("%d", &n);
index = (char***)calloc(n, sizeof(char));
if (index == NULL)
{
    printf("allocation Failed");
    return;
}
return index;
}
char** GetDefinitions()
{
int n = 0;
char **definition;
printf("please insert the number of defintions you want to add to the word\n");
scanf("%d", &n);
definition = (char**)calloc(n+1, sizeof(char));
if (definition == NULL)
{
    printf("allocation failed");
    return;
}
return definition;
}
int main()
{
char *** dptr = GetIndexes();
if (dptr == NULL)
{
    printf("memory Allocation failed");
}
int indexcount = sizeof(dptr) / sizeof(char),i;
for (i = 0; i < indexcount; i++)
{
    printf("word number %d\n", i + 1);
    *dptr[i] = GetDefinitions();
}
printf("%p",dptr);

}

i tried running the debugger in VS2013 and after i enter the number of defintions i want it crashed with this message:

Unhandled exception at 0x01103FB0 in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x00000000.

i missed an allocation of something but i cant quite figure out what i missed,

thanks in advance

Puloko
  • 81
  • 1
  • 2
  • 7
  • For whatever reason you have `char ***` it is very likely a bad idea, and also insufficient space, it should be `calloc(n, sizeof(char **))`; or even `calloc(n, sizeof(char *));` or `calloc(n, sizeof(void *));` i.e. `n` pointers, but not `calloc(sizeof(char));`. Also, don't cast `calloc`/`malloc` it could hide bugs in your program. – Iharob Al Asimi Jan 14 '15 at 10:37
  • what do you think this `*dptr[i] = GetDefinitions();` does? – Iharob Al Asimi Jan 14 '15 at 10:40
  • 3
    [Don't cast the return value of `malloc()` and friends in C](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – unwind Jan 14 '15 at 10:41
  • what do you think is the result of `int indexcount = sizeof(dptr) / sizeof(char)`? – mch Jan 14 '15 at 10:46
  • 1
    http://stackoverflow.com/a/25750950/775806 – n. m. could be an AI Jan 14 '15 at 10:58
  • i just went through the code and i think the problem is this line int indexcount = sizeof(dptr) / sizeof(char) – Puloko Jan 14 '15 at 11:01
  • @Puloko did you know [this](http://stackoverflow.com/tour)? and could you please send me an email with the details of what your program should do? I need to see why are so many people using this `***` thing, is there no better solution? iharob@gmail.com – Iharob Al Asimi Jan 14 '15 at 11:15

2 Answers2

4

Your program is very broken

  1. You allocate n char ***s but only request space for n chars and also do it for char **, to prevent this kind of mistake you may use the sizeof operator this way

    char ***index;
    index = calloc(n, sizeof(*index));
    

    and

    char **definition;
    definition = calloc(n, sizeof(*definition));
    

    and as you see casting calloc makes it harder and it's not necessary.

  2. You have a return statement that doesn't return anything an GetIndexes() as well as one in GetDefinitions.

    They should return NULL if you want to handle failure in the caller function

    return NULL;
    
  3. You erroneously use the sizeof operator to determine the number of char *** pointer allocated in

    int indexcount = sizeof(dptr) / sizeof(char)
    

    this will be either 4 or 8 depending on the architecture i.e. the size of a pointer divided by 1 sizeof(char) == 1 always.

    You can't compute that value, you simply have to keep track of it. The size

  4. You dereference the triple pointer twice and try to assign a double pointer to it

    *dptr[i] = GetDefinitions();
    

    here the operator precedence is also an issue, but regardless of that, this is wrong, may be what you meant was

    dptr[i] = GetDefinitions();
    
  5. This is not going to make your program crash, but it's certainly important to free all malloced pointers before exiting the program.

Here is a suggestion for your code to work, ignore it's purpose since it's not clear what you are trying to do

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

char ***GetIndexes(unsigned int *count)
{
    char ***index;

    printf("please insert the number of words you want to add to dictionary > ");
    scanf("%u", count);

    index = calloc(*count, sizeof(*index));
    if (index == NULL)
    {
        printf("allocation Failed");
        return NULL;
    }

    return index;
}

char **GetDefinitions(unsigned int *count)
{
    char **definition;

    printf("please insert the number of defintions you want to add to the word > ");
    scanf("%u", count);

    definition = calloc(*count + 1, sizeof(*definition));
    if (definition == NULL)
    {
        printf("allocation failed");
        return NULL;
    }
    return definition;
}

int main()
{
    unsigned int indexCount, i;
    char      ***dptr = GetIndexes(&indexCount);

    if (dptr == NULL)
    {
        printf("memory Allocation failed");
    }

    for (i = 0; i < indexCount; i++)
    {
        unsigned int definitionsCount;

        printf("Word number %u\n", i + 1);
        dptr[i] = GetDefinitions(&definitionsCount);
        if (dptr[i] != NULL)
        {
            /* use dptr[i] here or maybe somewhere else, but when you finish */
            free(dptr[i]);
        }
    }
    printf("%p", dptr);
    /* now if you are done using dptr */
    free(dptr);

    return 0;
}
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • the return just drops the program if allocation fails, is that wrong? i dont really think i can do exit(1) in a function that isnt a main() – Puloko Jan 14 '15 at 10:51
  • "*the return just drops the program if allocation fails, is that wrong?*" It's ok, but not nice. You may call `exit()` any time, but in signal handlers. @Puloko – alk Jan 14 '15 at 10:59
  • 1+ for a complete answer. Still all `int`s shall be `size_t`s. – alk Jan 14 '15 at 11:03
  • @alk I didn't notice that, since there are so many other issues, but it's a good suggestion, i will fix it. – Iharob Al Asimi Jan 14 '15 at 11:05
  • "*... be `size_t`s.*" or at least `unsigned`. – alk Jan 14 '15 at 11:06
  • edited the *dptr[i] thing, the indexcount is 1 when i tried making the array with 4 cells,can i free an allocated memory within a function? – Puloko Jan 14 '15 at 11:07
  • It's because of the 3rd point of my answer, try the code I fixed. Read it, and try to understand it. – Iharob Al Asimi Jan 14 '15 at 11:10
  • @iharob why does the Getindexes() function has an input value and a scanf value? – Puloko Jan 14 '15 at 11:31
  • Because that way you keep track of the number of indices, otherwise you could just `scanf` in main and pass it to `GetIndexes` function, but you must keep track of that value, the `sizeof` operator cannot give that value, it's not possible to compute it. – Iharob Al Asimi Jan 14 '15 at 11:34
0

As already mentioned in the comment this is a very bad idea and just using double pointers is good here. But the below fixes should be done if you want to use pointers to allocate memory

index = calloc(n, sizeof(char));

should be

index = calloc(n, sizeof(char **));

and

definition = calloc(n+1, sizeof(char));

should be

definition = calloc(n+1, sizeof(char *));
Gopi
  • 19,784
  • 4
  • 24
  • 36
  • the point of the third degree pointers is to make dictionary dictionaryPTR>>Dynamic Array of Pointers To Another dynamic Array of pointers>>Dynamic array of pointers pointing towards addresses of arrays of words or strings which are dynamically allocated – Puloko Jan 14 '15 at 10:42
  • @Puloko Don't you think just a double pointer will serve your purpose? – Gopi Jan 14 '15 at 10:43
  • to be honest i have no idea – Puloko Jan 14 '15 at 10:44
  • @Puloko Get rid of triple pointers ans re-design the code using double pointers and I think that is a much better idea and much easier instead of this. I don't see a need for triple pointer here – Gopi Jan 14 '15 at 10:46
  • i will have to qsort the words so i think that triple pointer is still necessary, – Puloko Jan 14 '15 at 10:48
  • @Puloko `qsort` is not a good reason for triple pointers. But i must say, I have seen a lot of `dictionary` programs here in SO, that use `***`, I don't get it? is it that your teacher is telling you guys to do so? – Iharob Al Asimi Jan 14 '15 at 11:04
  • Could someone (propably you *Gopi*) give a serious reason for this wide spread triple-pointer bashing? Three levels of indirection naturllay lead to triple-pointers. An array of arrays of C-"string"s is three levels of indirection. So what? – alk Jan 14 '15 at 11:09
  • "*just using double pointers is good here.*" would you mind giving an example? – alk Jan 14 '15 at 11:12
  • @iharob yes pretty much, its a requirement to work with the triple pointer – Puloko Jan 14 '15 at 11:25