简体   繁体   中英

Modifying pointer array in C function

I've got a problem when dealing with one- and two-dimensional dynamically allocated arrays in C. I have found similar questions, however none of them helped me so I'm asking a new one.

Here is my problem. With the function below I want to add a new element into a two dimensional char array. Size is not the problem, I increment somewhere outside.

void addElem(char ***tabs, int size, char *new) {
    *tabs[size] = (char*)malloc(sizeof(char)*strlen(new));
    *tabs[size] = new;
    *tabs = (char **)realloc(*tabs, size * sizeof(char *));
}

In the code the function is called this way:

int i;
char *tmp;
char **array = (char **)malloc(sizeof(char *));
//some stuff, also initializing i and tmp
addElem(&array, i, tmp);

The problem is that the function even if allocates the data, it does not save any data there (for example, strcmp gives SIGSEGV using **array). When debugging similar functions (managing one-dim int arrays), I found out that they in fact work properly inside these functions, the data is just not saved after returning.

I tried to show as small amount of code as possible, but if it helps here is the full code (with addElem function renamed to dodajDoTablicySlow). Thanks.

Consider your addElem() function:

void addElem(char ***tabs, int size, char *new) {
    *tabs[size] = (char*)malloc(sizeof(char)*strlen(nowy));
    *tabs[size] = new;
    *tabs = (char **)realloc(*tabs, size * sizeof(char *));
}

This function doesn't write the new element where you think it does. The array subscripting operator ( [] ) has higher precedence than the indirection operator ( * ), so *tabs[size] means "the thing pointed to by element size of array tabs ", not "element size of the array pointed to by tabs ".

Also, if size is the current size of the dynamic array -- as in the number of char * members *tabs has space to accommodate -- then (*tabs)[size] is beyond its capacity. Even if it requested sufficient space to include that position, which it doesn't, the realloc() call would not in any way be guaranteed to expand the memory allocated for *tabs to include that space. It is entirely free to put the new allocation somewhere else instead. It may sometimes need to do so when the new size is larger than the old, but it is free to do so even when the new size is smaller. At some point, uses of this function are likely to lose data in the reallocation.

In addition, your function leaks memory. It malloc() s space almost sufficient for the string pointed to by global variable nowy , then overwrites the only pointer to that space with function argument new .

Furthermore, your function has no good way to signal failure.

This would be a correct, safer, non-leaky implementation:

/*
 * Ensures that the dynamic array of char * pointed to by '*tabs' has
 * sufficient capacity for exactly 'size' + 1 elements, and stores the
 * value of 'el' at the last position.  Updates *tabs with a pointer to
 * the (possibly different) location of the enlarged array.  Returns the
 * location of the array, or NULL if memory allocation fails (in which
 * case '*tabs' is unchanged, and still a valid pointer to allocated memory).
 */
char **addElem(char ***tabs, size_t size, char *el) {
    char **newtabs = realloc(*tabs, (size + 1) * sizeof(char *));

    if (newtabs) {
        *tabs = newtabs;
        (*tabs)[size] = el;
    }

    return newtabs;
}

A very simple program about triple pointer:

#include <stdio.h>
void printElem(int ***tabs) {
    printf("%d\n",***tabs);

}
int main()
{
     printf("Hello, World!\n");
     int b = 7;
     int *d;
     int **t;
     d = &b;
     t = &d;
     printElem(&t);

     return 0;
}


output:
sh-4.3# main                                                                                                                                                                                                  
Hello, World!                                                                                                                                                                                                 
 7  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM