0

I am trying to transpose a 2D char array (in C) of unknown size rows and columns at run time. I use malloc to create the array and for loops to copy the chars form the original array to the new array. I am testing on a sample array of size 9x15 to create an array of 15x9 and the code works until my outer loop i =11 and then crash. In debug mode it shows Exception: Access violation writing to location 0xcdcdcdcd. The original array is read in from a file and is created using the same malloc code and works just fine. I have tried moving the code to main, but get the same exception. I am confused on how it does not create the array properly and would appreciate some input on how to correct the code or trouble shoot the issue better. My code is here

char **dest_grid = malloc(sizeof(char*) * source_col);
if (dest_grid == NULL) {
    printf("Memory not assigned\n");
    exit(EXIT_FAILURE);
}
else {
    for (i = 0; i <= source_row; i++) {
        dest_grid[i] = malloc(sizeof(char) * source_row);
        }
    for (i = 0; i < source_col; i++) {
        for (j = 0; j < source_row; j++) {
            if (j == source_row) {  
                dest_grid[i][j] = '\0';
            }
            else {
                dest_grid[i][j] = source_grid[j][i];
            }
        }
    }
}
for (i = 0; i < source_col; i++) {
        free(dest_grid[i]);
}
free(dest_grid);

edit: The size of the array is provided from the file when read into memory. Multiple arrays are read in from the file of various sizes.

CheezHed
  • 1
  • 1
  • 3
    Think of what happens if the 2D array is not square. But anyway [edit] and post a [mcve]. – Jabberwocky Feb 17 '21 at 08:27
  • 1
    Unrelated to your issue, this code will be needlessly inefficient because you aren't using a 2D array. If you would [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) instead, you could use a 2D array instead, which would be much faster since it could utilize data cache. – Lundin Feb 17 '21 at 08:43
  • 1
    @Lundin I love that answer, and have used it many times. Alas, however, it will not apply to a fairly large (admittedly idiotic) player in the toolchain game, namely MSVC, which still does not (and never will, so they say) support VLAs, even the particle of their syntax you profess. `void foo(size_t x, int (*ar)[x]) {}` , for example, will puke all over any MSVC C compiler, running at any/all language standards, including C99 and C11. There are no plans to ever change that either, last I heard (was awhile ago, so ymmv). Still, love that answer. – WhozCraig Feb 17 '21 at 09:11
  • @WhozCraig Still you can always allocate "mangled arrays" with one single malloc call in the old school C89 way: `int* arr = malloc(x*y*sizeof *arr); ... arr[y*i + j] = ... ;` This is ugly but at least allocates the data in a single heap chunk, which is so much better than a pointer look-up table to individual heap chunks. `int** table_thing = malloc(x * sizeof(int*));` was _never_ the correct way, save for some special cases where you want an array of strings etc with individual lengths, then it is fine. – Lundin Feb 17 '21 at 09:16
  • @Lundin Absolutely, and I've been relegated to doing that very thing where I need blistering performance and still have to contend with a corporate policy that refuses to embrace the joys of clang :-P – WhozCraig Feb 17 '21 at 09:18
  • @Jabberwocky I am not sure I see your point on the array being square. I updated the code sample and tested it as a standalone project. The code itself seems to function properly. I think I am having an issue with large memory allocations. This function is operating on an array that was allocated previously and it seems that the area that is allocated is providing me with memory that I can not use. – CheezHed Feb 18 '21 at 07:01
  • @Lundin I tried to implement the code from your linked post, however it seems that my IDE does not like that I use values for the rows and columns that are not fixed values, they are read in from the file. I have tried the code in your second comment as well `int* arr = malloc(x*y*sizeof *arr);` which does complete the operation. The error I get with that code is when I try to free the array my debugger claims that the heap was corrupted and exits. Am I asking for too much memory? I have allocated the array twice, once to read in the original array and again to transpose it. – CheezHed Feb 18 '21 at 07:11
  • @CheezHed You need to use a standard C compiler. It appears you are using some outdated one from 1990 such as Turbo C or Visual Studio. I'd recommend using gcc or clang instead. As for why your new code doesn't work, please ask a separate question about it. – Lundin Feb 18 '21 at 07:18
  • @Lundin I did not mean for that to appear as a separate question, I was trying to make a note that I have already tried the other method with no success. On a positive note, the code from your linked post does work with a different compiler, gcc, which I have setup in Eclipse but was not using. I am new to c and have been using Visual Studio, not knowing that it was outdated. This still presents with an error when i try to free the memory which I am trying to figure out now and will make a new post at a later time. Thanks for your help and pointing me to a good compiler! – CheezHed Feb 19 '21 at 06:12

1 Answers1

1

After char **dest_grid = malloc(sizeof(char*) * src_c); allocates space for src_c pointers, the loop beginning for (i = 0; i <= src_r; i++) attempts to fill it in with src_r+1 pointers, which is wrong.

if (dest_grid == NULL) tests for memory allocation failure, but this is after dest_grid was already used, in assigning values to dest_grid[i].

There is no code to test whether the memory allocations for dest_grid[i] fail.

dest_grid[i][j] = NULL; should be dest_grid[i][j] = '\0';, because NULL represents a null pointer, not a null character, and some definitions of it may cause compiler errors in this use.

free(dest_grid); releases the memory allocated to dest_grid, but the individual allocations to dest_grid[i] have not been freed.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • point taken on sloppy code, its hard to know what is broken when it is chaos. I have thrown a lot of different things into the code and have gotten a little turned around. I have cleaned it up and can run it stand alone to my main project and get a correct output.I think I am having a memory allocation issue. – CheezHed Feb 18 '21 at 07:13