C语言中奇怪的内存损坏

C语言中奇怪的内存损坏,c,clang,C,Clang,在回答另一个问题时,我写了一些初始化和打印2D数组的简单代码。但是发生了一些非常奇怪的事情 #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++ ) {

在回答另一个问题时,我写了一些初始化和打印2D数组的简单代码。但是发生了一些非常奇怪的事情

#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);
}
如果我链接到glib-2之类的包中,则损坏会更频繁

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
内存位置都正确。初始化期间所有行都正常。没有编译器警告
-fsanize=地址
未发现任何错误

是什么导致该行损坏?有人能重复这个问题吗

$ 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

您正在将int指针数组分配为int数组,从而导致一些意外行为。幸运的是,修复起来非常简单

替换此行:

int **board = malloc( sizeof(int) * num_rows );
int **board = malloc( sizeof(int *) * num_rows );
这一行:

int **board = malloc( sizeof(int) * num_rows );
int **board = malloc( sizeof(int *) * num_rows );
或者,为了避免将来出现此类错误,正如Jonathan Leffler在下面的评论中指出的那样,您可以对尝试分配的取消引用变量执行
sizeof
运算符,这样您就不必担心类型是否正确:

int **board = malloc( sizeof(*board) * num_rows );

int**board=malloc(sizeof(int)*行数)-->
int**board=malloc(sizeof(int*)*num_行)@Christiangibons谢谢,4对8,这样就可以了。把这个写进回答里,我会接受的。奇怪的
-fsanize=address
没有捕捉到它。简单的规则是:
sizeof
参数中的
*
比指针的类型少。已经有数百个类似的问题,回答这个问题没有多大意义。@Barmar一个更简单的规则是使用
sizeof*variable\u name
或者在某些方面更好,
int**board=malloc(sizeof(*board)*行数)
@JonathanLeffler啊,是的,这个符号本来可以避免这个问题。。