首页 > 解决方案 > 当我想用它的地址初始化一个二维字符数组时出现段错误

问题描述

我正在做一个项目,我需要在另一个函数中修改一个二维数组,而不是我创建它的地方。但是,我尝试这样做会遇到段错误,但我不明白这个问题。

这是我正在尝试做的代码:

# include <stdlib.h>
# include <stdio.h>

void    test(char ***tab)
{
    *tab = malloc(sizeof(char *) * 2);
    *tab[0] = malloc(sizeof(char) * 5);
    *tab[0][0] = 't';
    printf("%c\n", *tab[0][0]);
    *tab[0][1] = 'e';
    printf("%c\n", *tab[0][1]);
    *tab[0][2] = 's';
    *tab[0][3] = 't';
    *tab[0][4] = '\0';
    tab[1] = NULL;
}

int main()
{
    char **tab1;
    char **tab2;
    tab1 = malloc(sizeof(char *) * 2);
    tab1[0] = malloc(sizeof(char) * 5);
    tab1[0][0] = 't';
    tab1[0][1] = 'e';
    tab1[0][2] = 's';
    tab1[0][3] = 't';
    tab1[0][4] = '\0';
    tab1[1] = NULL;
    printf("tab1 %s\n", tab1[0]);

    test(&tab2);
    printf("%s\n", tab2[0]);
}

我编译我的代码:

gcc -fsanitize=address test.c

这是输出

tab1 test
t
AddressSanitizer:DEADLYSIGNAL
=================================================================
==12145==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x0000004c22c8 bp 0x7ffc58e533d0 sp 0x7ffc58e532c0 T0)
==12145==The signal is caused by a READ memory access.
==12145==Hint: address points to the zero page.
    #0 0x4c22c7 in test (/home/user42/Bureau/a.out+0x4c22c7)
    #1 0x4c2aaa in main (/home/user42/Bureau/a.out+0x4c2aaa)
    #2 0x7fc4aebc4b96 in __libc_start_main /build/glibc-2ORdQG/glibc-2.27/csu/../csu/libc-start.c:310
    #3 0x41aaa9 in _start (/home/user42/Bureau/a.out+0x41aaa9)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/user42/Bureau/a.out+0x4c22c7) in test
==12145==ABORTING

如您所见,tab1初始化时不会导致任何段错误,但tab2在初始化第一个字符后会导致。为什么会这样?

标签: arrayscsegmentation-fault

解决方案


问题是一元运算*符比运算符的关联更松散[],因此您需要在test. 以下修复它。

另请注意,完全tab[1] = NULL;没有*。它必须是(*tab)[1] = NULL;(见下文)。这是一个重要的修复,因为没有它,代码会受到未定义行为的影响:

void    test(char ***tab)
{
    *tab = malloc(sizeof(char *) * 2);
    (*tab)[0] = malloc(sizeof(char) * 5);
    (*tab)[0][0] = 't';
    printf("%c\n", (*tab)[0][0]);
    (*tab)[0][1] = 'e';
    printf("%c\n", (*tab)[0][1]);
    (*tab)[0][2] = 's';
    (*tab)[0][3] = 't';
    (*tab)[0][4] = '\0';
    (*tab)[1] = NULL;
}

推荐阅读