0

In a program I'm currently writing, I have this function, which reads the input and stores each line in an entry of an array of characters. n is a number previously given in the input, and represents the number of lines to be read.

char **linelist(int n)
{
    int i, j;
    char **list;
    list = calloc(n, sizeof(char *));
    for (j = 0; j < n; j++){
        list[j] = calloc(MAX_STR, sizeof(char));
    }
    for (i = 0; i < n; i++){
        fgets(list[i], (MAX_STR), stdin);
    }
    return list;
}

This function seems to be working correctly, for the output of a certain command supposed to give the input as output always matches the supposed output in tests.

Then, we have the following function, which takes the array returned by the aforementioned one and further splits the lines into words, generating a two-dimentional matrix, which has n lines, corresponding to the number of lines in the input, and therefore, their number in list, and an arbitrary number of rows, with the words of each line being store in each entry.

char ***createmat(int n, char **list)
{
    char ***matrix;
    int i, x, j, k, l, y, z;
    char *buffer;
    const char separators[] = {' ','\t',',',';','.','?','!','"','\n'};
    printf("F0\n");
    buffer = calloc(MAX_STR, sizeof(char));
    y = 0;

    matrix = calloc(n, sizeof(char**));
    for(z = 0; z < n; z++) {
        matrix[z] = calloc(n, sizeof(char*)); // line 100
        for(i = 0; i < n; i++) {
            matrix[z][i] = calloc(MAX_STR, sizeof(char));
        }
    }
    printf("F1\n");
    for(x = 0; x < n; x++){
        for(j = 0, l = 0; list[x][j] != '\0'; j++, l++){
            buffer[l] = tolower(list[x][j]);
            for(k = 0; k < 9; k++){
                if(list[x][j] == separators[k]){
                    if(l != 0){
                        buffer[l] = '\0';
                        printf("F2\n");
                        stringcpy(buffer,matrix[x][y++]);  //line 114
                        printf("F3\n");
                    }
                    l = -1;
                }
            }
        }
        matrix[x][y+1] = "\n";
    }
    printf("F4\n");
    return matrix;
}

This is the function, which starts with allocating memory for matrix, a process which raises no errors in Valgrind. The problem seems to come with the part that's supposed to separate and store the words. Based on the tests, it seems to work when each line has only one word, but doesn't when any line has multiple words. The printf statements were put in for debugging purposes and running the following input in a terminal:

3  //what the functions receive as int n - the number of lines
the sky
is pink and yellow and
not uncute

Gives the following output:

F0
F1
F2
F3
F2
F3
F2
F3
F2
Segmentation fault (core dumped)

As for running it in Valgrind returns the following:

==7599== Invalid read of size 8
==7599==    at 0x400D01: createmat (proj.c:114)
==7599==    by 0x4015A7: main (proj.c:241)
==7599==  Address 0x5201428 is 0 bytes after a block of size 72 alloc'd
==7599==    at 0x4C2ABB4: calloc (vg_replace_malloc.c:593)
==7599==    by 0x400BBC: createmat (proj.c:100)
==7599==    by 0x4015A7: main (proj.c:241)
==7599== 
==7599== Invalid read of size 1
==7599==    at 0x40087D: stringcpy (proj.c:12)
==7599==    by 0x400D16: createmat (proj.c:114)
==7599==    by 0x4015A7: main (proj.c:241)
==7599==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

And the stringcpyfunction is the following:

void stringcpy(char *s, char *t)
{
    while ((*s++ = *t++) != '\0'); //line 12
}

I've been trying to figure out what's wrong forever, but to no avail, being that I have very few experience in C. Any help would be appreciated. Thank you.

1

2 Answers 2

0

If you are trying to copy the value that pointer holds, you can use strcpy function of C I think, here you can find the reference about function. But I am not sure if your stringcpy method caused the error.

Sign up to request clarification or add additional context in comments.

Comments

0

One possible problem is that variable y never appears to be reset to zero. It appears as if it should be reset to zero when reaching the end of a line.

One other possibility is that if there are more than n words in a given line, then that would result in writing past the end of allocated memory.

Edit Based on the addition of the source for stringcpy, it appears you have the parameters backwards in the call. I think it should be:

stringcpy(matrix[x][y++],buffer);  //line 114

Note that the following line causes a memory leak (the assignment of the constant string "\n" causes the pointer to the allocated memory in that spot to be lost:

    matrix[x][y+1] = "\n";

5 Comments

The y variable being reset is true, it should be reset, and I really have no idea why I didn't do that. Thanks for pointing it out. However, that's not the problem, as the output remains the same. As for the n, writing only two words per line while the number is 3 ends up giving the same result, so that shouldn't be the problem. Only way that could be relevant would be having a problem whenever there are more than n words in total.
It should probably be set to zero at the very top of the outermost loop (I think). The outer most loop is the one that processes a single input line. There may be other issues too. Stepping through it in a debugger and inspecting variables would be a great way to figure it out (good learning experience).
Yeah, after your previous suggestion I set it to zero at the top of the outermost loop, so that's exactly what I did. Still didn't change anything. As for inspecting the variables, it's definitely a good advice, and I'll certainly follow it. I'm just quite afraid the problem is related to the memory allocation, since those are issues I always have trouble solving.
@Dusk252: The allocation looks correct in the sense that it allocates an n x n two-dimensional array where each element points to an allocated buffer of length MAX_STR. So if you don't have more than n words in a line and no word is longer than MAX_STR-1, then it should be fine to hold the data. Stepping through the code should help identify if there are other logic errors.
No word should be longer than MAX_STR, as that is the limit set. Thanks a lot for your answer, it's reassuring to know it's probably not an allocation problem. I'll check everything else further.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.