C Can't read the last property in struct properly - c

I'm having trouble getting the last property in a struct.
This is my struct
#define MAX_FILE_NUM 64
#define MAX_FILE_NAME_LENGTH 15
typedef struct
{
char file_name[MAX_FILE_NAME_LENGTH]; //file name
int size; //size of the file
int used; //0 represents the file is not used and 1 represents the file is used
int block; //the index of data block that stores the file
int block_count; //the number of blocks the file used
int file_descriptor_count; //the number of file descriptors are referring to the file
}file_detail;
Assuming the code update the directory info at i = 0
file_detail * directory_block_ptr = (file_detail *)malloc(4096);
int create(char *name){
if(name == NULL || find_file(name) != -1 || strlen(name) > MAX_FILE_NAME_LENGTH || super_block_ptr->files >= MAX_FILE_NUM){
printf("%s\n", "ERROR: file create condition not satified");
return -1;
}
//create the file
for(int i = 0; i < MAX_FILE_NUM; i++){
//update directory info
if((directory_block_ptr+i)->used == 0){
strcpy((directory_block_ptr+i)->file_name, name);
(directory_block_ptr+i)->size = 0;
(directory_block_ptr+i)->file_descriptor_count = 0;
(directory_block_ptr+i)->used = 1;
(directory_block_ptr+i)->block = -1;
(directory_block_ptr+i)->block_count = 0;
printf("%d\n", (directory_block_ptr+i)->file_descriptor_count);//correct output 0
break;
}
}
printf("%d\n", (directory_block_ptr+0)->file_descriptor_count);//incorrect output
//open the file
int result = fs_open(name);
if(result != -1)
{
printf("%s: %s %s\n", "File", name, "created successfully");
return 0;
}
return -1;
}
But when I'm trying to access the file_decsriptor_count outside of the for loop, I get random numbers like 1868958256.
create("test");

I'm going to go out on a limb here and propose that the memory from malloc is uninitialized, and that's what's going on here.
In the loop (and rewriting into proper array format as suggested by #Gerhardh):
for (int i = 0; i < MAX_FILE_NUM; i++) {
//update directory info
if( directory_block_ptr[i].used == 0) {
// assign stuff
printf("%d\n", directory_block_ptr[i].file_descriptor_count);//correct output 0
break;
}
}
The OP says they get the correct value, but we don't know that it's the [0] index, right? If there's junk in position directory_block_ptr[0].used, then that position will not be touched and the loop will move onto the next one. We just don't know which one is being found.
Recommend to OP: change the printf in the loop to be:
printf("%d set in position [%d]\n", directory_block_ptr[i].file_descriptor_count, i);
and see if it's telling you position [0] or [1] or whatever. My guess is not-zero.
Recommend to OP, change your initialization at the top to be:
#define DIRECTORY_BLOCK_SIZE 4096
file_detail *directory_block_ptr = malloc(DIRECTORY_BLOCK_SIZE);
memset(directory_block_ptr, 0, DIRECTORY_BLOCK_SIZE);
This allocates the same amount of memory, but insures that it's all set to zero, then run it again.
Also, this is more a matter of style than of substance, I'd do the loop this way by defining a much simpler variable name for access throughout the loop, it's easier to follow.
for(int i = 0; i < MAX_FILE_NUM; i++){
file_detail *fd = &(directory_block_ptr[i]); // shorthand
//update directory info
if(fd->used == 0){
strcpy(fd->file_name, name);
fd->size = 0;
fd->file_descriptor_count = 0;
fd->used = 1;
fd->block = -1;
fd->block_count = 0;
printf("%d set in position [%d]\n", fd->file_descriptor_count, i);
break;
}
}

Related

I want to get integer values from three text files using multiple threads and check if these are prime number if so store them in new file

The function used here is working but as i am sending each threads to do this job the threads are overdoing or doing noofthreads time because of the for loops used for them when creating. I am out of logic here what can i do so that after succesfully loading and checking the 1159999 values from multiple text files i want to store them in seperate text file.
`
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
pthread_mutex_t lck;
typedef struct{
int start;
int end;
}Innerstruct;`
struct data{
FILE **fptr;
Innerstruct *inner;
int numberthreads;
int totalno;
};
int primecount=0;//to store prime numbers count
int nofiles=3;
void countlines(int *count,FILE **fptr,int nofiles){ //counts the no of lines of cordinates from the text file
int i;
*count = 0;
for(i=0;i<nofiles;i++){
fseek(fptr[i], 0, SEEK_SET);
char line[256]; // buffer to store each line
while(fgets(line, sizeof(line), fptr[i])){
if(strlen(line) > 1){ // only increment if line is not empty so that this doesn't count blank spaces (*count)++;
}
}
}
}
void *getstorecountprime(void *p){
FILE *fptr4;
fptr4 = fopen("PrimeNumber.txt","w");
if(fptr4==NULL){
printf("Error creating file");
}
struct data *d1 = p;
int i,j,k,num,start,end;
for(k=0;k<d1->numberthreads;k++){
start= d1->inner[k].start;
end = d1->inner[k].end;
for(j=start;j<=end;j++){
for(i=0;i<nofiles;i++){
fseek(d1->fptr[i], j, SEEK_SET);
fscanf(d1->fptr[i],"%d",&num);
if(checkprime(num)){
pthread_mutex_lock(&lck);
fprintf(fptr4,"%d\n",num);
primecount++;
pthread_mutex_unlock(&lck);
}
}
}
}
}
void main(){
//checking for any error on opening the files
FILE *fptr1,*fptr2,*fptr3;
// opening text files
fptr1 = fopen("PrimeData1.txt","r");
fptr2 = fopen("PrimeData2.txt","r");
fptr3 = fopen("PrimeData3.txt","r");
if(fptr1==NULL || fptr2==NULL || fptr3==NULL){
printf("Could not open all files");
exit(1);
}
pthread_mutex_init(&lck,NULL);
FILE *fptr[] = {fptr1,fptr2,fptr3}; //array of file pointer
int num_threads,sliceperthread,*numarray;
int i;
int totalcount = 0;//to store total numbers
pthread_t *id;
struct data d1;
countlines(&totalcount,fptr,nofiles);//counts the no of lines from txt files
numarray = malloc(totalcount*sizeof(int));//dma to store all datas in array
printf("Enter how many threads do you want:");
scanf("%d",&num_threads);
id = malloc(num_threads*sizeof(pthread_t));//dma thread equal to the number of thread
d1.inner = malloc(num_threads*sizeof(Innerstruct));//dma the inner structure containing
start and end
d1.fptr = malloc(nofiles*sizeof(FILE*));//dma the fptr as array of nofiles size
sliceperthread = totalcount/num_threads;
d1.fptr=fptr;//assigned the fptr of structure to array of file pointer created above
d1.numberthreads=num_threads;\
d1.totalno = totalcount;
d1.inner[0].start = 0;
d1.inner[0].end = sliceperthread;
for(i=1;i<=num_threads;i++){
d1.inner[i].start = d1.inner[i-1].end + 1;
d1.inner[i].end = d1.inner[i-1].end + sliceperthread;
}
for(i=0;i<num_threads;i++){
pthread_create(&id[i],NULL,getstorecountprime,&d1);
pthread_join(id[i],NULL);
}
printf("%d",primecount);
}
int checkprime(int n){
int i;
for(i=2;i<=n/2;i++){
if(n%i == 0){
return 0;
}else{
return 1;
}
}
}``
As you can see from the code that i tried using a nested structure for this process. I created a structure which will store file pointers array and another inner structure array having start and end so that this could be used for threads start and end point. So i used a for loop to create threads and assign them function sending the structure as parameter. I was expecting to get prime numbers in text file but because of the iteration the program just keeps on adding values to the file.
At least these problems:
No increment
(*count)++; is lost in a comment. #M Oehm
if(strlen(line) > 1){ // only increment if line is not empty so that this doesn't count blank spaces (*count)++;
}
Wrong checkprime(int n)
Hopefully with uniform formatting it is easy to see the loop only iterates, at most, once and fails to return a value when i < 2.
int checkprime(int n) {
int i;
for (i = 2; i <= n / 2; i++) {
if (n % i == 0) {
return 0;
} else {
return 1;
}
}
}
Save time, auto format code and enable all compiler warnings to rapidly identify various code problems.

trying to create an array of struct pointer but get heap/buffer/etc violation statistically

i have two structs
typedef enum { False = 0, True = 1 } bool;
//defenition of candy structure
typedef struct _Candy {
char candy_name[16];
bool vegan;
}Candy;
typedef struct _Child {
char child_name[16];
Candy *candy_of_child;
}Child;
now im trying to create an array of pointers that each one is Child type
[*Child,*Child...] etc
now i can initialize it i need to do it dynamically
the function that does in is:
int AllocateKidsArray(int NumOfKids, Child** ptr_to_child_arr) {
//=================================================
//"AllocateKidsArray" intializing an array of childrens
//Input: 1. int indicating the number of kids
// 2. pointer to an array of children
//Output: 1. return an int value {0}->Success {-1}->Failure
// 2. pointer to an empty initialized array of childerns
//=================================================
// array of length NumOfKids, consisting of Child pointers
Child **ptr_to_childs = malloc(NumOfKids * sizeof(Child*));
int i;
for (i = 0; i < NumOfKids; i++) {
ptr_to_childs[i] = malloc(sizeof(Child));
strncpy((*ptr_to_childs[i]).child_name, "", 16);
(*ptr_to_childs)[i].candy_of_child = NULL;
}
*ptr_to_child_arr = *ptr_to_childs;
//for (i = 0; i < NumOfKids; i++) {
// free(ptr_to_childs[i]);
//}
//free(ptr_to_childs);
return 0;
}
im calling it from the main in the following manner:
int main(int argc, char** argv) {
//=================================================
if (argc < 3) {
printf("Incorrect number of arguments. Please invoke the program \n\t./program.exe < input.txt> <output.txt> \n");
exit(1);
}
int i, lines, checker = 0;
Candy *test = NULL;
char* name_test = NULL;
char* candy_test = NULL;
char* line = "Tamar,Apple\n";
int* NumLinesFile = NULL;
Child *ArrayOfChild = NULL;
.
.
.
//GetNumLines check
printf("%s\n", argv[0]);
printf("%s\n", argv[1]);
printf("%s\n", argv[2]);
GetNumLines(argv[1], &NumLinesFile);
lines = *NumLinesFile;
*NumLinesFile = NULL;
printf("%d\n", lines);
//=================================================
//AllocateKidsArray check
//AllocateKidsArray(lines, &ArrayOfChild);
AllocateKidsArray(lines, &ArrayOfChild);
//ImportKidsArray check
ImportKidsArray(argv[1], lines, &ArrayOfChild);
for (i = 0; i < lines; i++) {
//ArrayOfChild[i].candy_of_child = (Candy*) malloc(sizeof(Candy*));
printf("%s,%s\n", ArrayOfChild[i].child_name, ArrayOfChild[i].candy_of_child->candy_name);
}
//=================================================
and im statistically get heap/buffer violation
i suspect this function but i dont know what is wrong with it.
after the init of the array i pass it to another function that fills it in:
int ImportKidsArray(char* file_addr, int num_kids, Child** array_of_kids_to_fill) {
//=================================================
//"ImportKidsArray" reads the file and assign each valid line to cell in the array
//Input: 1. string to a location of a file
// 2. int indicating the number of kids
// 3. pointer to an array of children
//Output: 1. return an int value {0}->Success {-1}->Failure
// 2. pointer to an initialized array of childerns
//=================================================
FILE *fp;
char character;
char line[32];
int i = 0, j = 1, checker = 0, arr_count = 0;
char* TempChild = NULL;
char* TempCandy = NULL;
Child *arr = *array_of_kids_to_fill;
fp = fopen(file_addr, "r");
// Check if file exists
if (fp == NULL) {
printf("Could not open file %s", file_addr);
return -1;
}
while (!feof(fp)) {
fgets(line, 32, fp);
checker = ParseLine(line, &TempChild, &TempCandy);
GetCandy(TempCandy, &(arr[arr_count].candy_of_child));
strncpy((arr[arr_count]).child_name, TempChild, 16);
arr_count++;
}
return 0;
}
please if anyone can help, it will save my life :)
You want to change to ArrayOfChild. Passing it's address from main().
Change it by appropriately de-referencing it.
*ptr_to_childs = malloc(NumOfKids * sizeof(Child));
Then do rest of the operation on *ptr_to_childs. That will retain the change that you made in the called function.
Also check the return value of malloc. And free(using free()) the memory dynamically allocated.
If you notice carefully you will see in the ArrayOfChild() function you are working with a local variable Child **ptr_to_childs. You certainly don't want that as that variable will not be alive when the function ends.
Also while (!feof(fp)) is not appropriate to use. Check this link for that.
Another thing is check the return value of char *fgets(char *str, int n, FILE *stream).
On success, the function returns the same str parameter. If the
End-of-File is encountered and no characters have been read, the
contents of str remain unchanged and a NULL is returned.

Access to Typedef struct pointer which is passed as double pointer to function. Access inside the function

I have difficulty in dealing with access to structure members inside a function, and structure instancies are double pointer arguments. I am using strcpy and strcmp and it seems, to me (I used debuger), to do the bad things.
First, I have created structure using typedef, instanciated it 2 times and allocated memory for one of them.
Second, I have created function loadVariablesToMemory to which I am passing instanciated structure instancies as double pointers (2nd row - after //Functions comment).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
//FUNCTIONS
int loadVariablesToMemory(const char* fileName, const char* fileAccessMode, varData **dynamicData, varData **tmp);
//DECLARATION
typedef unsigned short int UINT16;
typedef struct data {
char varName[10];
UINT16 value;
} varData;
int main(){
//ALLOCATING MEMORY
varData *dynamicData;
dynamicData = (varData*)malloc(sizeof(varData));
varData *tmp;
tmp = NULL;
int numOfVars = loadVariablesToMemory("u02v1_input_03.txt", "r", &dynamicData, &tmp);
return 0;
}
Problem:
Inside the function loadVariablesToMemory I am trying to access allocated "variables" of structure instantiated and declared above, using:
.....
if(strcmp((*(dynamicalData+j-1))->varName, buffer) == 0){
.....etc.
strcpy((*(dynamicalData+numOfVars-1))->varName, buffer);
.....etc.
I run the debugger and all seems to work [also If I rewrite entire function outside into Main it works (with little changes with double pointers now single pointers)] but I got stuck in the rows where I use strcpy(); and strcmp() functions and I dont know why and I am little bit desperate, because these two semms to be only two things that prevent me from creating a working function and I am getting desperate as I am dealing with this problem almost 10 hours without any real progress.
COMPLETE FUNCTION loadVariablesToMemoryDECLARATION:
int loadVariablesToMemory(const char* fileName, const char* fileAccessMode, varData **dynamicalData, varData **tmpal) {
FILE *fSource = fopen(fileName, fileAccessMode);
char oneChar = '\0';
char buffer[10];
memset(buffer,'\0',10); //inicialization of buffer chars to \0
int i = 0;
int varOrNum = 0;
int numOfVars = 0;
bool match = false;
while (!feof(fSource)) {
oneChar = fgetc(fSource); //Load letter in file
if((oneChar == ' ') | (oneChar == '\n')) {
i = 0;
if((strcmp(buffer,"NOT") == 0) || (strcmp(buffer,"AND") == 0) || (strcmp(buffer,"OR") == 0) || (strcmp(buffer,"LSHIFT") == 0) || (strcmp(buffer,"RSHIFT") == 0) || (strcmp(buffer,"->") == 0)) {
memset(buffer,'\0',10);
}
else{
varOrNum = atoi(buffer); //returns (0) if varOrNum is variable (0)
if((varOrNum == 0) & (buffer[0] != '0'))
{ //if varOrNum is a variable (0)
for(int j = 0; j<=numOfVars; j++) { //control in memory for match of variable name
//HERE SEEMS NOT TO WORK - this is just random try if strcpy will work
//strcpy((*(dynamicalData+j-1))->varName, buffer);
//HERE SEEMS NOT TO WORK
if(strcmp((*(dynamicalData+j-1))->varName, buffer) == 0){
memset(buffer,'\0',10);
match = true; //match found
break;
}
else
match = false; //no match found
} //endForCycle
if(match == false){ //no match found
numOfVars++; //number of variables for allocation
tmpal = (varData*)realloc((*dynamicalData), numOfVars * sizeof(varData));
if(!tmpal) { //or equal to NULL
//printf("Could not resize/reallocate memory %i times \n", numOfVars);
}
else{
dynamicalData = tmpal;
strcpy((*(dynamicalData+numOfVars-1))->varName, buffer);
printf("%s \n", (*(dynamicalData+numOfVars-1))->varName);
}
}
}
varOrNum = 0; //if varOrNum is a number (1)
memset(buffer,'\0',10);
}
}
else{
buffer[i] = oneChar;
i++;
}
} //endWhileCycle (!feof(fSource))
fclose (fSource);
return numOfVars;
}
INSIDE INPUT FILE: u02v1_input_03.txt
0 -> c
va OR dq -> v
NOT cx -> dr
kk RSHIFT 3 -> km
NOT cx -> dq
3 AND v -> fx
lf RSHIFT 2 -> lg
Can anybody be so nice and help me with that? Thank you very much.
Try something like this:
if((varOrNum == 0) && (buffer[0] != '0')) {
int j;
for(j = 0; j<numOfVars; j++) {
if(strcmp(dynamicalData[j]->varName, buffer) == 0)
break;
}
if(j>=numOfVars) {
numOfVars++; //number of variables for allocation
tmpal = (varData*)realloc((*dynamicalData), numOfVars * sizeof(varData));
if(!tmpal) { //or equal to NULL
//printf("Could not resize/reallocate memory %i times \n", numOfVars);
}
else{
dynamicalData = tmpal;
strcpy(dynamicalData[numOfVars-1]->varName, buffer);
printf("%s \n", dynamicalData[numOfVars-1]->varName);
}
}
}
varOrNum = 0; //if varOrNum is a number (1)
memset(buffer,'\0',10);
In the 1st line you missed a &.
In the 1st loop (j==0) you do a strcmp dynamicalData+j-1 which means dynamicalData[-1]

int var getting bizarre values

Int value 'j' is getting weird results when i keep trying to debug it. I'm not sure if it's a problem with my school's compiler or if it's my code. Thanks for the help.
GCC Version:
Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.7/2.95.2/specs
gcc version 2.95.2 19991024 (release)
My segment of code that's messing up:
void sFlag(DIR * dirp, int c, char *dirname)
{
struct dirent *dp;
struct stat statbuf;
struct stat statarray[c];
struct stat tempstat;
char fullfilename[MAXSZ];
int i;
int boo;
int j; /*<--------- variable that's messing up*/
while((dp = readdir(dirp)) != NULL)
{
snprintf(fullfilename, MAXSZ, "%s/%s", dirname, dp->d_name);
if(stat(fullfilename, &statbuf) == -1)
printf("Could not read file %s\n", dp->d_name);
else if(isHiddenFile(dp->d_name))
{
statarray[i] = statbuf;
i++;
}
}
/*As far as i know all the code above works fine*/
/*bubble sort that will sort array by logical file size*/
while(boo)
{
j = 0;
boo = 0;
while(j < c)
{
fprintf(stderr, "%d\n", j); /*print debug info*/
if(statarray[j].st_size < statarray[j+1].st_size)
{
tempstat = statarray[j];
statarray[j] = statarray[j+1];
statarray[j+1] = tempstat;
boo = 1;
}
j++;
}
}
for(j = 0; j < c; j++)
{
printf("%s\t%ld\t%s\n", dp->d_name, statarray[j].st_size, ctime(&statarray[j].st_mtime));
}
}
So everytime i run this the fprintf prints out the value for j as:
0
1
2
3
4
-12975991
???????Where did it get that number from???
Obviously I get a segmentation fault from an array index out of bounds
any thoughts?
You're most likely trampling memory and overwriting the content of j. This loop:
while(j < c)
{
fprintf(stderr, "%d\n", j); /*print debug info*/
if(statarray[j].st_size < statarray[j+1].st_size)
{
tempstat = statarray[j];
statarray[j] = statarray[j+1];
statarray[j+1] = tempstat;
boo = 1;
}
j++;
}
Notice that it accesses statarray[j+1], but statarray is defined as
struct stat statarray[c];
meaning that on the last iteration, j+1 == c, which is out of bounds. Writing to that index in the array will trample other things on the stack, which could include j, and explain why you get a wacky-sounding value.
There are some nifty tools that can make this easier to find that you might consider, like valgrind.
In this block,
while(j < c)
{
fprintf(stderr, "%d\n", j); /*print debug info*/
if(statarray[j].st_size < statarray[j+1].st_size)
{
tempstat = statarray[j];
statarray[j] = statarray[j+1];
statarray[j+1] = tempstat;
boo = 1;
}
j++;
}
You are accessing unauthorized memory when j is equal to c-1. That would mess things up. You can't expect predictable behavior after that.
You have a fresh variable j in the while loop, the outer j is never set.

LibAIFF CloseFile: Pointer being freed was not allocated occurs randomly

I have written a piece of code that attempts to search a directory and its subfolders for two AIFF files and using the LibAIFF library to import and then perform some processing operations on them.
Part 1: Searching the directory for the files
For this part of the program, I need to look for the files (which can be thought of as identical AIFF files except for a difference in their filenames) with known names (for example SineSweepA.aiff and SineSweepB.aiff) and then construct the absolute path to it (the length of which I am unaware of (since my program needs to work on different computers where the AIFFs can be located within different subfolders within a MainDirectory - see code below) but know will be less than 200 characters in length). I am able to do this successfully and consistently using the following piece of code:
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);
}
So by using the above code, I am able to successfully search for two AIFF files with given filenames by searching through subfolders with a known MainDirectory, construct their absolute paths and store them in tempFilepath and tempFilepathR. The next step is to import these two files and this is where I run into a problem.
Part 2: Importing the files
The problem I run into is as follows: I implemented the LibAIFF library to import the files. The issue is that if I run the program, say N times, then on some of the runs, the first file gets imported but not the second, on other runs the second gets imported but not the first (note that if the first doesn't get imported, the program stops). Before I explain the error, please know that there is no issue with the AIFF files, for the sake of this problem you can assume they are identical and that even their absolute paths and filenames are identical except one has a suffix A.aiff and the other B.aiff. These file paths are stored as strings in identically defined variables (tempFilepath and tempFilepathR).
Here is the rest of the necessary part of my code continued from above
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.
}
The break always occurs within the import_sweeps() function (sometimes for the first AIFF and sometimes for the second). The function is shown below
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;
}
Inside import_sweeps() above, the AIFF file is ALWAYS successfully read by calling the function AIFF_ReadSamples32Bit(fileref, samples, nSamplePts);. Therefore, the temp value is never -1. Whenever an error (as described above and I will give the actual error message below) happens, it ALWAYS occurs when it tries to call AIFF_CloseFile(fileref);.
Shown below are the functions AIFF_ReadSamples32Bit and AIFF_CloseFile as defined in the LibAIFF library.
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;
}
and
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;
}
The break occurs at AIFF_ReadClose(ref); EVERYTIME. So I have also shown this function below.
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;
}
The break always occurs as shown above. The following is the error message: (25693,0x7fff7db87310) malloc: * error for object 0x4000000000000000: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
So basically, the above error occurs unpredictably. When it doesn't occur, my code works perfectly. Any help as to how I might solve this problem is much appreciated.
IF ANYONE IS WILLING TO DOWNLOAD THE LIBAIFF LIBRARY TO INVESTIGATE FURTHER AND HELP ME OUT, the link to the library is: http://aifftools.sourceforge.net/libaiff/.
Thanks in advance for any suggestions!
1, please confirm buffer2 has been initialized with NULL before using. In all your pasted codes, I can not find any assignment or memory allocation for buffer2.
2, please assign the pointer with NULL after calling free, like:
if (r->buffer)
{
free(r->buffer);
r->buffer = NULL;
}
if (r->buffer2)
{
free(r->buffer2);
r->buffer2 = NULL;
}
If all this can not resolve you problem, please give more code about buffer2.

Resources