cmemory-managementmalloc

Mallocing int* inside of int** gives unexpected integer values in the first and sometimes second allocation


I am having this problem. Basically I want to parse an integer string to an int** where the sub int arrays are two long. The first index is the digit and the second is the power of ten associated to the digit.

For example 12345 would give [[1, 4], [2, 3], [3, 2], [4, 1], [5, 0]]

Here is the code:

#include <stdlib.h>

int    ft_strlen(char *str)
{
    int    count;

    count = 0;
    while (*str++)
        count++;
    return (count);
}

int **parray(char *str)
{
    int **ret;
    int len;
    int i;

    len = ft_strlen(str);
    ret = (int **)malloc(sizeof(int) * len);
    if (ret == NULL)
        return (NULL);
    i = 0;
    while (i < len)
    {
        ret[i] = (int *)malloc(sizeof(int) * 2);
        if (ret[i] == NULL)
            return (NULL);
        ret[i][0] = str[i] - '0';
        ret[i][1] = len - 1 - i;
        i++;
    }
    return (ret);
}

This then get tested in a main function as follows:

#include <stdio.h>

int main()
{
    char *str = "1255555555555555";
    int**ret = parray(str);
    int i = 0;
    while (i < ft_strlen(str))
    {
        printf("%d ", ret[i][0]);
        printf("%d ", ret[i][1]);
        printf("\n");
        i++;
    }
}

This for some reason prints out:

29791280 0 
29791408 0 
5 13 
5 12 
5 11 
5 10 
5 9 
5 8 
5 7 
5 6 
5 5 
5 4 
5 3 
5 2 
5 1 
5 0 

Note that the program works fine with strings less or equal to 4 digits. The first two non working values also always change when u run the program again. Im assuimng there is some overflow somewhere but I don't know where, nor how. Im fairly new to c so please excuse me if this is a silly mistake.


Solution

  • ret = (int **)malloc(sizeof(int) * len); is wrong. The type of ret is int **. It is a pointer to int *. You are allocating space for int *. So you want the size of int *.

    Generally, it is preferable to calculate the size from the thing you are assigning to:

    ret = malloc(len * sizeof *ret);`
    

    *ret is a sample of what ret will point to, so sizeof *ret is the size of one of those things. In this case, it will be the size of an int *. This form automatically adjusts the allocation size to whatever type ret is. For example, if you change the declaration of ret later, while working on your program, the size here will automatically be correct without needing another edit.

    Also, do not cast the return value of malloc in C. (C++ is different.) There is no need for it, and it can mask a failure to declare malloc (because an include of a header was accidentally omitted).