调用 getChar 和 printf 似乎修改了不相关的数据

Calls to getChar and printf seem to modify unrelated data

我写了一个分配和初始化二维数组的函数,就像这样 -

static state **symbols;

void initNFAStates()
{
    int i,j;
    numStates = 256;
    symbols = (state**)malloc(numStates * sizeof(char));
    for(i = 0;i < numStates;i++)
    {
        symbols[i] = (state*)malloc(NUMSYMBOLS * sizeof(state));
        for(j = 0;j < NUMSYMBOLS;j++)
            symbols[i][j] = 0;
    }
}

和一个打印这个数组的函数,就像这样 -

void printNFAStateTable()
{
    int i, j; 
    for(i = 0;i < numStates;i++)
    {
        printf("%d \t",i);
        for(j = 0;j < NUMSYMBOLS;j++)
            printf("%ld",symbols[i][j]);
        printf("\n");
    }
}

当从 main() 函数连续调用时,它们都工作正常。但是,以下代码在仅读取数组的前 32 行后会导致段错误。

int main(int argc, char **argv)
{
    int i;
    clock_t begin, end;
    double timeTaken;
    currNFAState = 0;
    initNFAStates();


    if(getChars(argc,argv) != NULL)
    {
        printNFAStateTable();
        begin = clock();
        regex();
        ...

类似地,printf() 函数会导致同样的问题,但仅在打印浮点数时出现 -

int main(int argc, char **argv)
{
    int i;
    clock_t begin, end;
    double timeTaken;
    currNFAState = 0;
    initNFAStates();
    printf("A floating point number - %f",0.0124f);
    printNFAStateTable();
    ...

我知道这与 symbols 数组是静态的有关,因为当数组是全局数组时不会出现此问题。谁能解释为什么会这样?

这不是您所期望的:

符号[i][j] = 0;

原因是这假设了一个单独分配的内存块,组织为一个二维数组。那不是你创造的。

您的代码表明第一个维度的大小为 256,如下所示:

状态符号[256][NUMSYMBOLS];

如果你在全局或堆栈上分配。这将是一个大小为 256 * NUMSYBOLS * sizeof( state ) 的 RAM 块,其中每一行都是高级的 NUMSYMBOLS * sizeof( state )。

然而,您正在做的是在一个 RAM 块中创建一个指针数组,然后为每一行分配额外的 RAM 块。它们不相关,因此使用 2D 数组语法无法进行访问。

首先需要访问指向该行的指针,从概念上讲:

state *state_row = symbols[i];

这给了你行。现在,获取列;

stat * state_cell = state_row[j];

这被展开以展示如何思考它,您可以轻松地选择其他特定方式来访问适当的单元格。

鉴于此声明:

static state **symbols;

此分配不正确:

symbols = (state**)malloc(numStates * sizeof(char));

*symbols的类型是state *;这是您动态分配的数组元素的类型,我有信心断言您机器上的指针大于 char。这将是一个更合适的分配:

symbols = malloc(numStates * sizeof(*symbols));

(请注意,您不需要转换 malloc() 的 return 值,并且有充分的理由不这样做。)

由于没有为您要使用的所有指针分配足够的内存,您的程序在尝试访问超出分配范围的索引处的元素时表现出未定义的行为。该 UB 很容易以库函数的形式出现,它会修改您不希望它们修改的内存。