Search code examples
c++memory-managementmallocnew-operatordynamic-memory-allocation

Return 2D char array from function in c++ and print it


This is my code and I want to return 2D dimension array [10][8] and [10][20] from my function, but i get an error !! (Segmentation fault).

Please help me !! I need this for my project. Finally i want to print this array and I cant do this because of the error.

Can someone help me fix this and print that?

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cstring>

using namespace std;

char **getWords(int level)
{
    if (level == 1)
    {
        char **words = new char *[8];
        strcpy(words[0], "Pakistan");
        strcpy(words[1], "Portugal");
        strcpy(words[2], "Tanzania");
        strcpy(words[3], "Thailand");
        strcpy(words[4], "Zimbabwe");
        strcpy(words[5], "Cameroon");
        strcpy(words[6], "Colombia");
        strcpy(words[7], "Ethiopia");
        strcpy(words[8], "Honduras");
        strcpy(words[9], "Maldives");
        return words;
    }
    //For Hard Level
    else if (level == 2)
    {
        char **words = (char **)malloc(sizeof(char *) * 20);
        strcpy(words[0], "Tajikistan");
        strcpy(words[1], "Uzbekistan");
        strcpy(words[2], "Azerbaijan");
        strcpy(words[3], "Bangladesh");
        strcpy(words[4], "Luxembourg");
        strcpy(words[5], "Madagascar");
        strcpy(words[6], "Mauritania");
        strcpy(words[7], "Montenegro");
        strcpy(words[8], "Mozambique");
        strcpy(words[9], "New Zealand");

        return words;
    }
}

int main()
{
    getWords(1);

    return 0;
}

Solution

  • By doing

    char **words = new char *[10];
    

    You are only allocating memory for the pointers, not for the memory blocks where the actual strings are to be stored, you need to allocate memory for that too:

    char **words = new char *[10]; //space for 10 pointers
            
    for(int i = 0; i < 10; i++){
        words[i] = new char[10]; // space for 10 characters each line, 8 is not enough
    }                            // you need at least 9 because of the ending nul byte
    
    strcpy(words[0], "Pakistan");
    strcpy(words[1], "Portugal");
    //...
    

    In main, assing them to a pointer to pointer and print them as if it was an array of strings:

    char** words = getWords(1);
    
    for(int i = 0; i < 10; i++){
        std::cout << words[i] << std::endl;
    }
    

    Live demo

    The same goes for the second part which uses malloc.

    char **words = (char**)malloc(sizeof *words * 10); //space for 10 pointers
    
    for(int i = 0; i < 10; i++){
        words[i] = (char*) malloc(20); //space for 20 characters each line
    }
    

    Live demo

    In a normal situation, when the program doesn't end right away you would have to free the memory:

    For memory allocated with new:

    for (int i = 0; i < 10; i++) 
    {
        delete words[i];
    }
    delete words;
    

    For the memory allocated with malloc:

    for(int i = 0; i < 10; i++)
    {
        free(words[i]);
    }
    free(words);  
    

    This can be tricky in your case because you return 2 types of memory allocation deppending on the option you pass as parameter, my advice is that you use that same option to choose how to deallocate the memory.

    P.S.: Using C++ containers like std::vector and std::string would make your job easier, you wouldn't need to handle the memory yourself.