I'm new to the C language. The subject of memory allocation is especially new to me, so naturally I have a few questions.

I'm going to base a couple of my questions on the following sample program. It will return a NULL terminated string of plus characters.

Code:
char *doTest(int length) {
        char *test = malloc(sizeof(char));
        char *reallocation = NULL;
        int i = 0;
        int size = 1;

        if (test == NULL) {
                return NULL;
        }

        for (i = 0; i < length; i++) {
                size = size + sizeof(char);
                reallocation = realloc(reallocation, size);

                if (reallocation == NULL) {
                        free(test);
                        return NULL;
                }

                test = reallocation;
                test[i] = '+';
        }

        test[i] = 0;

        return test;
}

int main(void) {
        char *test = doTest(5);

        if (test != NULL) {
                printf(test);
        }

        free(test);

        return 0;
}
1. In doTest, I used two pointers for memory reallocation. Both pointers should point to the same memory location. If realloc fails, I can avoid a memory leak by freeing the test pointer and stop. If realloc succeeds, I can set the test pointer to the reallocation pointer and continue. Is this a good strategy?

2. As a follow-up to the question above, is the test pointer sometimes "invalid"? I think if realloc moves the memory location someplace else, the test pointer wont point to a valid location. It becomes "valid" again once I assign it to the reallocation pointer. If my statement is correct, do you have any suggestions on how to avoid this situation?

3. I've noticed that if I allocate memory for multiple pointers, and store each pointer in an array, it's not enough to just free that array. I need to use a loop and free each pointer individually.

Example:

Code:
char **doTest(void) {
        char **array = malloc(sizeof(char *) * 2);

        array[0] = malloc(sizeof(char) * 7);
        array[0] = "Test 1";
        array[1] = malloc(sizeof(char) * 7);
        array[1] = "Test 2";

        return array;
}

int main(void) {
        char **test = doTest();

        for (i = 0; i < 2; i++) {
                free(test[i]);
        }

        free(test);

        return 0;
}
Note: I would normally check for NULL above, but for clarity, I left that out.

It would be tedious to include the loop and two free calls more than once. A function would be convenient. In a C library, is it common to include functions for freeing returned pointers?