LibAIFF CloseFile: o ponteiro liberado não foi alocado ocorre aleatoriamente

Eu escrevi um pedaço de código que tenta procurar em um diretório e suas subpastas por dois arquivos AIFF e usando a biblioteca LibAIFF para importar e depois executar algumas operações de processamento neles.

Parte 1: Pesquisando no Diretório pelos Arquivos

Nesta parte do programa, preciso procurar os arquivos (que podem ser considerados arquivos AIFF idênticos, exceto por uma diferença em seus nomes de arquivos) com nomes conhecidos (por exemplo, SineSweepA.aiff e SineSweepB.aiff) e, em seguida, construir o caminho absoluto para ele (cuja extensão eu desconheço (já que meu programa precisa trabalhar em computadores diferentes onde os AIFFs podem estar localizados em subpastas diferentes dentro de umaMainDirectory - veja o código abaixo), mas saiba que terá menos de 200 caracteres). Consigo fazer isso com êxito e consistência usando o seguinte trecho de código:

void file_search(char* parentDir, char* subFolder, char* filenamePrefix, char* tempString, char* tempFilepath, int* foundFlag, int* level);
int32_t *import_sweeps(char* sweepFilepath, uint64_t* numSamples, int* numChannels, double* samplingRate, int* bitDepth, int* segmentSize, int* importFlag);

int main()
{
    ...
    char MainDirectory[200] = "/Users/rrr/Documents/Foldername1/";
    char tempFilepath[200], tempFilepathR[200], parentDir[200], filenamePrefix[200], subFolder[200], tempString[200]; 
    int level = 0, foundFlag = 0;
    int numChannels = 0;
    int bitDepth;
    int segmentSize;
    int importFlag = 0;
    int32_t *sweepRfile = NULL;
    uint64_t numSamples = 0, numSamplesR = 0;
    unsigned long templen;
    double samplingRate = 0.0;
    char *sweepFilepath = NULL, *sweepFilepathR = NULL; // Allocated to specific size later
    strcpy(parentDir, MainDirectory);
    strcat(parentDir, "SubFolderName1/");
    strcpy(tempFilepathR, parentDir);
    strcpy(filenamePrefix, "KnownFilenamePrefix1");

    // file_search() searches for a specific file with a known name and constructs the absolute path to the file and stores it in tempFilepathR. The function is shown further below.
    file_search(parentDir, subFolder, filenamePrefix, tempString, tempFilepath, &foundFlag, &level);

    if (foundFlag)
    {
        sprintf(tempFilepath, "%s%s/KnownFilenamePrefix1%s.aiff", parentDir, subFolder, subFolder);
        sprintf(tempFilepathR, "%s%s/KnownFilenamePrefix2%s.aiff", parentDir, subFolder, subFolder);
    }
    ...

    (to be continued in Part 2 of my question below)
}

void file_search(char* dir, char* subfolder, char* fileprefix, char* filename, char* filepath, int*flag, int* level)
{
    DIR *dp;
    struct dirent *entry; // entry is a pointer to the structure "dirent" defined in <dirent.h>
    struct stat statbuf; // the structure "stat" is defined in <stat.h>
    if((dp = opendir(dir)) == NULL) {
        fprintf(stderr,"Cannot open directory: %s\n", dir);
        return;
    }
    chdir(dir); // this sets the working directory to the string pointed to by "dir"
    while((entry = readdir(dp)) != NULL)
    {
        lstat(entry->d_name, &statbuf);
        if(S_ISDIR(statbuf.st_mode)) // Tests for a directory
        {
            // Found a directory
            if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0)
            {
                // Ignore . and ..
                continue;
            }

            if(level[0] < 1)
            {
                // Proceed down one level and search again
                strcpy(subfolder,entry->d_name);
                level[0] = level[0] + 1;

                // Recursive function call
                file_search(entry->d_name, subfolder, fileprefix, filename, filepath, postfilepath, flag, level);

                level[0] = level[0] - 1;

                if(flag[0] == 1)
                {
                    // Exit loop if a file was found at a lower level
                    break;
                }
            }
        }
        else
        {
            sprintf(filename, "%s%s.aiff", fileprefix, subfolder);
            if(strcmp(entry->d_name,filename) == 0)
            {
                // File found. Construct absolute path to file
                sprintf(filepath, "%s%s/%s", filepath, subfolder, filename); // Pass filepath outside
                flag[0] = 1; //Appropriate file found
                break;
            }
        }
    }
    chdir("..");
    closedir(dp);
}

Portanto, usando o código acima, posso pesquisar com êxito dois arquivos AIFF com determinados nomes de arquivos, pesquisando subpastas com um nome conhecido.MainDirectory, construa seus caminhos absolutos e armazene-os emtempFilepath etempFilepathR. O próximo passo é importar esses dois arquivos e é aqui que encontro um problema.

Parte 2: Importando os Arquivos

O problema que encontro é o seguinte: Eu implementei a biblioteca LibAIFF para importar os arquivos. O problema é que, se eu executar o programa, digamos N vezes, em algumas execuções, o primeiro arquivo será importado, mas não o segundo, em outras execuções, o segundo será importado, mas não o primeiro (observe que, se o primeiro não for ' para ser importado, o programa para).Antes de eu explicar o erro, saiba que não há problema com os arquivos AIFF. Para solucionar esse problema, você pode assumir que eles são idênticos e que mesmo os caminhos e nomes de arquivos absolutos são idênticos, exceto que um possui um sufixoA.aiff e o outroB.aiff. Esses caminhos de arquivo são armazenados como seqüências de caracteres em variáveis definidas de forma idêntica (tempFilepath etempFilepathR)

Aqui está o restante da parte necessária do meu código continuada de cima

int main()
{
    // Continued from above
    ...

    // Copy over exact file paths (I had to do this because the function AIFF_OpenFile which is part of the LibAIFF library and shown below refused to accept a statically allocated char variable such as tempFilepath)

        templen = strlen(tempFilepathR); // tempFilepath and tempFilepathR always have the same length
        sweepFilepath = malloc(templen + 1);
        strcpy(sweepFilepath, tempFilepath);

        // Proceed to import the FIRST AIFF (returned to sweepRfile from import_sweeps())
        sweepRfile = import_sweeps(sweepFilepath, &numSamples, &numChannels, &samplingRate, &bitDepth, &segmentSize, &importFlag);
        if (importFlag) // The import was successful
        {
            free(sweepFilepath);
            // Do some processing with the successfully imported AIFF
            free(sweepRfile);
        }
        else // The import was unsuccessful and sweepRfile (which is usually malloc'ed in the import_sweeps() function is not malloc'ed
        {
            free(sweepFilepath);
        }

        // Now for the SECOND AIFF (I can overwrite a lot of the variables used for the first AIFF because I don't need them)
        sweepFilepathR = malloc(templen + 1); // templen is assigned above
        strcpy(sweepFilepathR, tempFilepathR);

        // Proceed to import the SECOND AIFF (returned to sweepRfile from import_sweeps())
        sweepRfile = import_sweeps(sweepFilepathR, &numSamplesR, &numChannels, &samplingRate, &bitDepth, &segmentSize, &importFlag);
        if (importFlag) // The import was successful
        {
            free(sweepFilepathR);
            // Do some processing with the successfully imported AIFF
            free(sweepRfile);
        }
        else // The import was unsuccessful and sweepRfile (which is usually malloc'ed in the import_sweeps() function is not malloc'ed
        {
            free(sweepFilepathR);
        }
    ...
    // Rest of code in main is irrelevant because it doesn't even get there.
}

A interrupção sempre ocorre na função import_sweeps () (algumas vezes para o primeiro AIFF e outras para o segundo). A função é mostrada abaixo

int32_t *import_sweeps(char* sweepFilepath, uint64_t* numSamples, int* numChannels, double* samplingRate, int* bitDepth, int* segmentSize, int* importFlag)
{
    // Initialize files for importing */
AIFF_Ref fileref;

// Import Routine */
fileref = AIFF_OpenFile(sweepFilepath, F_RDONLY);
if(fileref)
{
    // File opened successfully. Proceed to intialize files for getting information about AIFF file
    uint64_t nSamples;
    int nSamplePts, channels, bitsPerSample, segSize, temp;
    double smpr;

    // Get AIFF file format details
    temp = AIFF_GetAudioFormat(fileref, &nSamples, &channels, &smpr, &bitsPerSample, &segSize);
    if (temp < 1) {
        fprintf(stderr,"Error getting audio format.\n");
        AIFF_CloseFile(fileref);
        return (int32_t) 0;
    }
    else
    {
        numSamples[0] = nSamples;
        samplingRate[0] = smpr;
        numChannels[0] = channels;
        bitDepth[0] = bitsPerSample;
        segmentSize[0] = segSize;
        nSamplePts = ((int) nSamples)*channels;
        int32_t *samples = malloc((nSamplePts+1) * sizeof(int32_t));

        // Read AIFF
        temp = AIFF_ReadSamples32Bit(fileref, samples, nSamplePts);
        if (temp != -1)
        {
            AIFF_CloseFile(fileref);
            importFlag[0] = 1;
            return samples;
        }
        else
        {
            fprintf(stderr,"Unable to read AIFF.\n");
            AIFF_CloseFile(fileref);
            return (int32_t) 0;
        }
    }
}
else
{
    fprintf(stderr,"Unable to open AIFF file.\n");
}
return (int32_t) 0;
}

Dentro de import_sweeps () acima, o arquivo AIFF é SEMPRE lido com êxito chamando a funçãoAIFF_ReadSamples32Bit(fileref, samples, nSamplePts);. Portanto, o valor temporário nunca é -1. Sempre que ocorre um erro (como descrito acima e mostrarei a mensagem de erro real abaixo), SEMPRE ocorre quando ele tenta chamarAIFF_CloseFile(fileref);.

Abaixo, são mostradas as funçõesAIFF_ReadSamples32Bit eAIFF_CloseFile conforme definido na biblioteca LibAIFF.

int AIFF_ReadSamples32Bit(AIFF_Ref r, int32_t * samples, int nSamplePoints)
{
int n = nSamplePoints;
void *buffer;
int i, j;
size_t h;
size_t len;
int segmentSize;
int32_t *dwords;
int16_t *words;
int8_t *sbytes;
uint8_t *inbytes;
uint8_t *outbytes;
uint8_t x, y, z;

if (!r || !(r->flags & F_RDONLY))
    return -1;
if (n % (r->nChannels) != 0)
    return 0;

if (n < 1 || r->segmentSize == 0) {
    if (r->buffer) {
        free(r->buffer);
        r->buffer = NULL;
        r->buflen = 0;
    }
    return -1;
}
segmentSize = r->segmentSize;
len = (size_t) n * segmentSize;

if ((r->buflen) < len) {
    if (r->buffer)
        free(r->buffer);
    r->buffer = malloc(len);
    if (!(r->buffer)) {
        return -1;
    }
    r->buflen = len;
}
buffer = r->buffer;

h = AIFF_ReadSamples(r, buffer, len);
if (h < (size_t) segmentSize) {
    free(r->buffer);
    r->buffer = NULL;
    r->buflen = 0;
    return 0;
}
n = (int) h;
if (n % segmentSize != 0) {
    free(r->buffer);
    r->buffer = NULL;
    r->buflen = 0;
    return -1;
}
n /= segmentSize;

switch (segmentSize) {
case 4:
    dwords = (int32_t *) buffer;
    for (i = 0; i < n; ++i)
        samples[i] = dwords[i];
    break;
case 3:
    inbytes = (uint8_t *) buffer;
    outbytes = (uint8_t *) samples;
    n <<= 2;    /* n *= 4 */
    j = 0;

    for (i = 0; i < n; i += 4) {
        x = inbytes[j++];
        y = inbytes[j++];
        z = inbytes[j++];
#ifdef WORDS_BIGENDIAN
        outbytes[i] = x;
        outbytes[i + 1] = y;
        outbytes[i + 2] = z;
        outbytes[i + 3] = 0;
#else
        outbytes[i] = 0;
        outbytes[i + 1] = x;
        outbytes[i + 2] = y;
        outbytes[i + 3] = z;
#endif
    }

    n >>= 2;
    break;
case 2:
    words = (int16_t *) buffer;
    for (i = 0; i < n; ++i) {
        samples[i] = (int32_t) (words[i]) << 16;
    }
    break;
case 1:
    sbytes = (int8_t *) buffer;
    for (i = 0; i < n; ++i) {
        samples[i] = (int32_t) (sbytes[i]) << 24;
    }
    break;
}

return n;
}

e

int AIFF_CloseFile(AIFF_Ref ref)
{
int r;

if (!ref)
    return -1;
if (ref->flags & F_RDONLY) {
    AIFF_ReadClose(ref); // BREAK OCCURS HERE EVERYTIME
    r = 1;
} else if (ref->flags & F_WRONLY) {
    r = AIFF_WriteClose(ref);
} else {
    r = -1;
}

return r;
}   

O intervalo ocorre àsAIFF_ReadClose(ref); TODA VEZ. Então, eu também mostrei esta função abaixo.

static void AIFF_ReadClose(AIFF_Ref r)
{
if (r->buffer)
    free(r->buffer);
if (r->buffer2)
    free(r->buffer2);  // THIS IS WHERE THE BREAK OCCURS EVERYTIME
Unprepare(r);
fclose(r->fd);
free(r);
return;
}

A interrupção ocorre sempre como mostrado acima. O seguinte é omensagem de erro: (25693,0x7fff7db87310) malloc:* erro para o objeto 0x4000000000000000: o ponteiro sendo liberado não foi alocado * defina um ponto de interrupção em malloc_error_break para depurar

Então, basicamente, o erro acima ocorreimprevisível. Quando isso não ocorre, meu código funciona perfeitamente.Qualquer ajuda sobre como resolver esse problema é muito apreciada.

Se alguém estiver disposto a baixar a biblioteca LIBAIFF para investigar mais adiante e me ajudar, o link para a biblioteca é:http://aifftools.sourceforge.net/libaiff/.

Agradecemos antecipadamente por todas as sugestões!

questionAnswers(1)

yourAnswerToTheQuestion