【问题标题】:Strange C error while freeing memory?释放内存时出现奇怪的 C 错误?
【发布时间】:2013-02-28 17:34:16
【问题描述】:

我仍在尝试让我的遗传算法工作(昨天我遇到了内存分配问题,因此在尝试释放它时出现了一个可怕的错误)但今天我有这段代码

while (iCurrentGen <= data->m_iMaxGenerations)
{
    arrfSelectedChromosomes = selection(&data[0], szChromosomes);
    iSelectedLen = order_descending_grid(arrfSelectedChromosomes);
    szAuxGen = crossover(&data[0], arrfSelectedChromosomes, szChromosomes, iSelectedLen);
    //szChromosomes is what I need to free after that call returns
    free_generation(&data[0], szChromosomes);//Code Explotion
    szChromosomes = szAuxGen;
    szAuxGen = NULL;
    ++iCurrentGen;
}

我在free_generation() 函数调用之前检查了它的内容,如下图所示:

(变量前四个值)

但是在free_generation()函数内部,同一个变量会丢失一些值(特别是当i取值为2,i是for循环索引时),如下所示:

(函数内部的变量值)

我将 free_generation 代码贴在下面:

void free_generation(struct INPUT_DATA* d, char** szChromosomes)
{
    int i;

    for (i = 0; i < d->m_iPopulationSize; ++i)
    {
        free(szChromosomes[i]);
    }

    free(szChromosomes);
    szChromosomes = NULL;
}

szChromosomes的定义如下:

char** szChromosomes = (char**)malloc(d->m_iPopulationSize * sizeof(char*));

srand(time(NULL));
for (i = 0; i < d->m_iPopulationSize; ++i)
{
    szChromosomes[i] = (char*)malloc((d->m_iBitsPChromosome + 1) * sizeof(char));
    for (j = 0; j < d->m_iBitsPChromosome; ++j)
    {
        szChromosomes[i][j] = rand_1_0(0.0, 1.0) == 1? '1' : '0';
    }
    szChromosomes[i][j] = '\0';
}

我需要澄清一下,这个值的丢失仅发生在顶部发布的 while 循环的第二次迭代之后。我的意思是在第一次运行时一切正常,但在这次迭代之后,第二次运行如上所述。

编辑:

我忘了包括循环控制变量的增量(感谢指出!不,它不是全局 xD)。我包括部分交叉代码:

    char** crossover(struct INPUT_DATA* d, float** arrfSelectedChromosomes, char** arrszChromosomes, int iChromosomesInGrid)
{
    int i;
    int iTIndex = 0, iRPos = 0;
    char* szFirstChromosome = NULL;
    char* szSecondChromosome = NULL;
    char* szFirstNewChrom = (char*)malloc((d->m_iBitsPChromosome + 1) * sizeof(char));
    char* szSecondNewChrom = (char*)malloc((d->m_iBitsPChromosome + 1) * sizeof(char));

    char** arrszNewPop = (char**)malloc(d->m_iPopulationSize * sizeof(char*));

    int iSplitPoint = (int)(d->m_iBitsPChromosome / 4);

    float fCrossOverProb = CROSSOVER_PROBABILITY; 

    srand(time(NULL));
    for (i = 0; i < d->m_iPopulationSize; i += 2)
    {
        iRPos = rand() % iChromosomesInGrid;
        iTIndex = (int)arrfSelectedChromosomes[iRPos][0];
        szFirstChromosome = arrszChromosomes[iTIndex];
        iRPos =  rand() % iChromosomesInGrid;
        iTIndex = (int)arrfSelectedChromosomes[iRPos][0];
        szSecondChromosome = arrszChromosomes[iTIndex];

        if (is_same_chromosome(szFirstChromosome, szSecondChromosome))
        {
            i -= 2;
            continue;
        }

        if (fCrossOverProb < CROSSOVER_PROBABILITY)
        {
            //if probability is lower than the defined prob. we keep both chromosomes
            strcpy(szFirstNewChrom, szFirstChromosome);
            strcpy(szSecondNewChrom, szSecondChromosome);
        }
        else
        {

            strcpy(szFirstNewChrom, szFirstChromosome);
            szFirstNewChrom[iSplitPoint] = '\0';
            strcat(szFirstNewChrom, &szSecondChromosome[iSplitPoint]);

            //Para crear el segundo hijo se realiza una operacion similar
            strcpy(szSecondNewChrom, szSecondChromosome);
            szSecondNewChrom[iSplitPoint] = '\0';
            strcat(szSecondNewChrom, &szFirstChromosome[iSplitPoint]);
        }

        arrszNewPop[i] = szFirstNewChrom;
        arrszNewPop[i + 1] = szSecondNewChrom;
    }

    return arrszNewPop;
}

【问题讨论】:

  • 如果您在 Linux 或 MacOS/X 下运行,请尝试安装 valgrind 并在其下运行您的程序。它可能会告诉你哪里出了问题。
  • 您的染色体数组包含重复的指针值。一旦你在同一个指针上使用了两次free,所有的地狱都会崩溃。顺便说一下,这发生在迭代 3 (i==2)。您需要跟踪这些重复值是如何在数组中结束的。
  • 我在 windows 下 Jeremy.. 重复的指针值是否会因为这样调用 strcat 而出现:strcpy(szFirstNewChrom, szFirstChromosome); szFirstNewChrom[iSplitPoint] = '\0'; strcat(szFirstNewChrom, &szSecondChromosome[iSplitPoint]); iSplitPoint 是一个介于 0 和 31 之间的整数。我正在创建一个连接两个染色体的新染色体。 szFirstNewChrom 在使用前分配 33 个字节
  • crossover() 实际上是如何工作的?此外,我在您的while() 循环中没有看到对循环控制变量iCurrentGen 的修改,所以显然这不是正在执行的所有代码(当然,除非它是一个全局的,这将是一个糟糕的设计)。
  • 复制指针是复制(分配)指针本身的结果,而不是指向字符。单步执行程序并观察染色体数组。

标签: c free pointer-to-pointer


【解决方案1】:

由于对mark a comment as an answer 的功能请求仍然被拒绝,我在此处复制上述解决方案。

n.m 你就是那个男人!非常感谢.. 这是重复指针的问题,这是由于交叉函数中的内存分配错误。我在函数开始时为 szFirstNewChrom 和 szSecondNewChrom 分配内存,但该内存用于 30 个不同的字符串。由于那个可怕的错误,free_generation 函数一直失败,因为它试图释放先前释放的指针。谢谢你们! ——豪尔赫·塞斯佩德斯

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 2023-03-13
    • 2021-04-22
    相关资源
    最近更新 更多