Reputation: 165318
In answering another question I wrote up what should be some simple code to initialize and print a 2D array. But something very strange is happening.
#include <stdio.h>
#include <stdlib.h>
void print_row( const int *row, size_t num_cols ) {
printf("%p\n", (void*)row);
for( size_t col_num = 0; col_num < num_cols; col_num++ ) {
printf(" %2d ", row[col_num]);
}
puts("");
}
int **make_board( const size_t num_rows, const size_t num_cols ) {
int **board = malloc( sizeof(int) * num_rows );
for( size_t row_num = 0; row_num < num_rows; row_num++ ) {
int *row = calloc( num_cols, sizeof(int) );
board[row_num] = row;
print_row(row, num_cols);
}
return board;
}
void print_board( int **board, const size_t num_rows, const size_t num_cols ) {
for( size_t row_num = 0; row_num < num_rows; row_num++ ) {
const int *row = board[row_num];
print_row(row, num_cols);
}
}
int main() {
size_t num_rows = 6;
size_t num_cols = 4;
puts("Making the board");
int **board = make_board(num_rows, num_cols);
puts("Printing the board");
print_board(board, num_rows, num_cols);
}
Running it, I occasionally get one corrupted row, but only ever in print_board
never in make_board
.
cc -Wall -Wshadow -Wwrite-strings -Wextra -Wconversion -std=c99 -pedantic -g -c -o test.o test.c
cc test.o -o test
Making the board
0x7fc4e6d00370
0 0 0 0
0x7fc4e6d001e0
0 0 0 0
0x7fc4e6d001f0
0 0 0 0
0x7fc4e6d00200
0 0 0 0
0x7fc4e6d00210
0 0 0 0
0x7fc4e6d00220
0 0 0 0
Printing the board
0x7fc4e6d00370
0 0 0 0
0x7fc4e6d001e0
-422575600 32708 -422575584 32708
0x7fc4e6d001f0
0 0 0 0
0x7fc4e6d00200
0 0 0 0
0x7fc4e6d00210
0 0 0 0
0x7fc4e6d00220
0 0 0 0
If I link in packages, like glib-2, the corruption happens more frequently.
cc -Wall -Wshadow -Wwrite-strings -Wextra -Wconversion -std=c99 -pedantic -g `pkg-config --cflags glib-2.0` -c -o test.o test.c
cc `pkg-config --libs glib-2.0` test.o -o test
The memory locations are all correct. All rows are fine during initialization. There's no compiler warnings. -fsanitize=address
finds no errors.
What might be causing that one row to become corrupted? Can anyone even repeat the problem?
$ cc --version
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin17.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$ uname -a
Darwin Windhund.local 17.6.0 Darwin Kernel Version 17.6.0: Tue May 8 15:22:16 PDT 2018; root:xnu-4570.61.1~1/RELEASE_X86_64 x86_64 i386 MacBookPro8,1 Darwin
Upvotes: 2
Views: 115
Reputation: 4370
You are allocating your array of int pointers as an array of ints resulting in some unexpected behavior. Simple enough fix, fortunately.
Replace this line:
int **board = malloc( sizeof(int) * num_rows );
With this line:
int **board = malloc( sizeof(int *) * num_rows );
Or, to avoid these kind of mistakes in the future, as pointed out by Jonathan Leffler below in the comments, you can perform the sizeof
operator on the dereferenced variable you are trying to allocate so you don't have to worry about getting the type correct:
int **board = malloc( sizeof(*board) * num_rows );
Upvotes: 5