C programming 2d dynamic string array

Hello and happy new year everyone !
I have to do this project for Christmas and my time is running out...
The project is to make an English to Greek dictionary and in order to do that i need a 2D dynamic array.
This is what i've come up with:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define s_size 256
void show_menu();
unsigned int Add_El( char**, char**,unsigned int);
void save_file( char**, char**,unsigned int);
int main()
{
    unsigned int Sum_of_Terms=0;
    char **En=NULL,**Gr=NULL;
    char ch,save;
   // Memory Initialization.
   En = ( char**)malloc(sizeof( char* ));
   Gr = ( char**)malloc(sizeof( char* ));
    do{
    show_menu();
    printf("\nInsert option: ");
    //scanf("%d",&ch);
    ch = getch();
    printf("\n");

    if(ch=='6')
    {
        do{
            printf("Would you like to save changes?(y/n): ");
            save = getch();
            printf("\n");

        }while(save!='y' && save!='n');
        if(save=='y')
            save_file(En,Gr,Sum_of_Terms);
        else
            exit(0);

    }

    if(ch>'6' || ch<'1') printf("Invalid choice!\n");
    switch(ch)
    {
        case '1':Sum_of_Terms = Add_El(En,Gr,Sum_of_Terms);
        break;
    }
    printf("\n Sum: %d",Sum_of_Terms);


}while(ch!='6');


return 0;
}
void show_menu()
{
    printf("\n\n********************************************");
    printf("\n***************** MENU *********************\n");
    printf("********************************************\n\n");
    printf("1. Insert new word. \n");
printf("2. Modify an existing entry. \n");
printf("3. Delete an entry. \n");
printf("4. Translate a word. \n");
printf("5. Translate a sentence. \n");
printf("6. EXIT.\n");
}
unsigned int Add_El(char **En,char **Gr,unsigned int w_count) // w_count = word count.
{
    int i;
    char s[s_size];
   w_count++;
    En = (char**)realloc(En,sizeof(char* )*(w_count));
Gr = (char**)realloc(Gr,sizeof(char* )*(w_count));

if(En==NULL || Gr==NULL)
    printf("Could Not Allocate Memory (1).\n");
else
{

        //English Word.
        if(En[w_count-1]==NULL)
            printf("Could not allocate memory (2).\n");
        else
        {
            printf("Insert English Word: ");
            //scanf("%s",&s);
            gets(s);
            En[w_count-1]=(char*)malloc((strlen(s)+1)*sizeof(char));
            //strcpy(En[w_count],s);
            En[w_count-1]=strdup(s);
        }


        //Greek Word.
        if(Gr[w_count-1]==NULL)
            printf("Could not allocate memory (2).\n");
        else
        {
            printf("Insert Greek Word: ");
            //scanf("%s",&s);
            gets(s);
            Gr[w_count-1]=(char*)malloc((strlen(s)+1)*sizeof( char));
            //strcpy(Gr[w_count],s);
            Gr[w_count-1] = strdup(s);

        }

    //Test_point 1.
    for(i=0;i<w_count;i++)
        printf("\n %s =  %s \n",En[i],Gr[i]);

}//else (1)

return w_count;
}

The problem I have is that while for the first 2 entries it works fine, at the third entry (w_count=3) it fails to allocate memory.
I've been trying to figure it out for quite a while but I haven't come up with anything yet and it's getting really annoying.
I 'd really appreciate some help. Thanks in advance!

I couldn't run this (i dont have conio.h) but I'm not sure why you keep casting the returns from malloc, as char* and char**.

I had a look but also don't have conio. Reading it is a bit difficult without cleaning up the code.

Anyway, this is your bug:

Your Add_El function is receiving a copy of your En pointer, not a reference to it, so it won't change the pointer En in main function when you realloc in Add_el. Check if I am correct:

Print your pointers (printf("%p", En)) before and after realloc to check if En pointer has changed or not inside Add_El, then print your pointers also in main before and after calling Add_El to see if the pointer En has changed in main. Your program will break as soon as En in main starts to mismatch En in Add_El. These are two different copies of the pointer.

You have the same problem with Gr - pointer in main and Gr pointer in Add_El - they are not same pointer, but two copies.

To help yourself develop this code further, I suggest you could simplify memory handling and improve readability by declaring a struct and reallocing an array of that struct:

struct X {
    char * En;
    char * Gr;
};

Then malloc and realloc array using sizeof(struct X) similar to this:

realloc(DictionaryArray,sizeof( struct X )*(w_count));

Keeping things together could help you finding memory-related bugs.

Also, consider putting the whole dictionary in one struct, and then passing a pointer to a copy of that struct to your Add_El function, to make sure you always have all your pointers in one place. Something like this:

struct Y {
    struct X * arrayOfWordPairs;
    unsigned int w_count;
};

The call to Add_El could then be simplified like this:

unsigned int Add_El(struct Y * dictionary);

And you can dereference w_count like this:

dictionary->w_count++;

and:

dictionary->arrayOfWordPairs[w_count - 1].En = strdup(ENGLISH_WORD);
dictionary->arrayOfWordPairs[w_count - 1].Gr = strdup(GREEK_WORD);

I can also see that this code will leak memory allocated in malloc, because the pointer is overwritten by strdup without being released:

En[w_count-1]=(char*)malloc((strlen(s)+1)*sizeof(char));
//strcpy(En[w_count],s);
En[w_count-1]=strdup(s);

I hope I am not going over your head (since your code is telling me that you are either a C beginner, or very stressed up).